FreeWRL/FreeX3D  3.0.0
duktape.c
1 /*
2  * Single source autogenerated distributable for Duktape 2.0.0.
3  *
4  * Git commit external (external).
5  * Git branch external.
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-2017 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 
40 /* AUTHORS.rst */
41 /*
42 * ===============
43 * Duktape authors
44 * ===============
45 *
46 * Copyright
47 * =========
48 *
49 * Duktape copyrights are held by its authors. Each author has a copyright
50 * to their contribution, and agrees to irrevocably license the contribution
51 * under the Duktape ``LICENSE.txt``.
52 *
53 * Authors
54 * =======
55 *
56 * Please include an e-mail address, a link to your GitHub profile, or something
57 * similar to allow your contribution to be identified accurately.
58 *
59 * The following people have contributed code, website contents, or Wiki contents,
60 * and agreed to irrevocably license their contributions under the Duktape
61 * ``LICENSE.txt`` (in order of appearance):
62 *
63 * * Sami Vaarala <sami.vaarala@iki.fi>
64 * * Niki Dobrev
65 * * Andreas \u00d6man <andreas@lonelycoder.com>
66 * * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
67 * * Legimet <legimet.calc@gmail.com>
68 * * Karl Skomski <karl@skomski.com>
69 * * Bruce Pascoe <fatcerberus1@gmail.com>
70 * * Ren\u00e9 Hollander <rene@rene8888.at>
71 * * Julien Hamaide (https://github.com/crazyjul)
72 * * Sebastian G\u00f6tte (https://github.com/jaseg)
73 * * Tomasz Magulski (https://github.com/magul)
74 * * \D. Bohdan (https://github.com/dbohdan)
75 * * Ond\u0159ej Jirman (https://github.com/megous)
76 * * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
77 * * Jeremy HU <huxingyi@msn.com>
78 * * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
79 * * Harold Brenes (https://github.com/harold-b)
80 * * Oliver Crow (https://github.com/ocrow)
81 * * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
82 * * Brett Vickers (https://github.com/beevik)
83 * * Dominik Okwieka (https://github.com/okitec)
84 * * Remko Tron\u00e7on (https://el-tramo.be)
85 *
86 * Other contributions
87 * ===================
88 *
89 * The following people have contributed something other than code (e.g. reported
90 * bugs, provided ideas, etc; roughly in order of appearance):
91 *
92 * * Greg Burns
93 * * Anthony Rabine
94 * * Carlos Costa
95 * * Aur\u00e9lien Bouilland
96 * * Preet Desai (Pris Matic)
97 * * judofyr (http://www.reddit.com/user/judofyr)
98 * * Jason Woofenden
99 * * Micha\u0142 Przyby\u015b
100 * * Anthony Howe
101 * * Conrad Pankoff
102 * * Jim Schimpf
103 * * Rajaran Gaunker (https://github.com/zimbabao)
104 * * Andreas \u00d6man
105 * * Doug Sanden
106 * * Josh Engebretson (https://github.com/JoshEngebretson)
107 * * Remo Eichenberger (https://github.com/remoe)
108 * * Mamod Mehyar (https://github.com/mamod)
109 * * David Demelier (https://github.com/markand)
110 * * Tim Caswell (https://github.com/creationix)
111 * * Mitchell Blank Jr (https://github.com/mitchblank)
112 * * https://github.com/yushli
113 * * Seo Sanghyeon (https://github.com/sanxiyn)
114 * * Han ChoongWoo (https://github.com/tunz)
115 * * Joshua Peek (https://github.com/josh)
116 * * Bruce E. Pascoe (https://github.com/fatcerberus)
117 * * https://github.com/Kelledin
118 * * https://github.com/sstruchtrup
119 * * Michael Drake (https://github.com/tlsa)
120 * * https://github.com/chris-y
121 * * Laurent Zubiaur (https://github.com/lzubiaur)
122 * * Neil Kolban (https://github.com/nkolban)
123 *
124 * If you are accidentally missing from this list, send me an e-mail
125 * (``sami.vaarala@iki.fi``) and I'll fix the omission.
126 */
127 
128 /*
129  * Replacements for missing platform functions.
130  *
131  * Unlike the originals, fpclassify() and signbit() replacements don't
132  * work on any floating point types, only doubles. The C typing here
133  * mimics the standard prototypes.
134  */
135 
136 /* #include duk_internal.h */
137 /*
138  * Top-level include file to be used for all (internal) source files.
139  *
140  * Source files should not include individual header files, as they
141  * have not been designed to be individually included.
142  */
143 
144 #if !defined(DUK_INTERNAL_H_INCLUDED)
145 #define DUK_INTERNAL_H_INCLUDED
146 
147 /*
148  * The 'duktape.h' header provides the public API, but also handles all
149  * compiler and platform specific feature detection, Duktape feature
150  * resolution, inclusion of system headers, etc. These have been merged
151  * because the public API is also dependent on e.g. detecting appropriate
152  * C types which is quite platform/compiler specific especially for a non-C99
153  * build. The public API is also dependent on the resolved feature set.
154  *
155  * Some actions taken by the merged header (such as including system headers)
156  * are not appropriate for building a user application. The define
157  * DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
158  * sections depending on what is being built.
159  */
160 
161 #define DUK_COMPILING_DUKTAPE
162 #include "duktape.h"
163 
164 /*
165  * User declarations, e.g. prototypes for user functions used by Duktape
166  * macros.
167  */
168 
169 DUK_USE_USER_DECLARE()
170 
171 /*
172  * Duktape includes (other than duk_features.h)
173  *
174  * The header files expect to be included in an order which satisfies header
175  * dependencies correctly (the headers themselves don't include any other
176  * includes). Forward declarations are used to break circular struct/typedef
177  * dependencies.
178  */
179 
180 /* #include duk_replacements.h */
181 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
182 #define DUK_REPLACEMENTS_H_INCLUDED
183 
184 #if !defined(DUK_SINGLE_FILE)
185 #if defined(DUK_USE_COMPUTED_INFINITY)
186 DUK_INTERNAL_DECL double duk_computed_infinity;
187 #endif
188 #if defined(DUK_USE_COMPUTED_NAN)
189 DUK_INTERNAL_DECL double duk_computed_nan;
190 #endif
191 #endif /* !DUK_SINGLE_FILE */
192 
193 #if defined(DUK_USE_REPL_FPCLASSIFY)
194 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
195 #endif
196 #if defined(DUK_USE_REPL_SIGNBIT)
197 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
198 #endif
199 #if defined(DUK_USE_REPL_ISFINITE)
200 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
201 #endif
202 #if defined(DUK_USE_REPL_ISNAN)
203 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
204 #endif
205 #if defined(DUK_USE_REPL_ISINF)
206 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
207 #endif
208 
209 #endif /* DUK_REPLACEMENTS_H_INCLUDED */
210 /* #include duk_jmpbuf.h */
211 /*
212  * Wrapper for jmp_buf.
213  *
214  * This is used because jmp_buf is an array type for backward compatibility.
215  * Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
216  * behave more intuitively.
217  *
218  * http://en.wikipedia.org/wiki/Setjmp.h#Member_types
219  */
220 
221 #if !defined(DUK_JMPBUF_H_INCLUDED)
222 #define DUK_JMPBUF_H_INCLUDED
223 
224 #if defined(DUK_USE_CPP_EXCEPTIONS)
225 struct duk_jmpbuf {
226  duk_small_int_t dummy; /* unused */
227 };
228 #else
229 struct duk_jmpbuf {
230  DUK_JMPBUF_TYPE jb;
231 };
232 #endif
233 
234 #endif /* DUK_JMPBUF_H_INCLUDED */
235 /* #include duk_exception.h */
236 /*
237  * Exception for Duktape internal throws when C++ exceptions are used
238  * for long control transfers.
239  *
240  * Doesn't inherit from any exception base class to minimize the chance
241  * that user code would accidentally catch this exception.
242  */
243 
244 #if !defined(DUK_EXCEPTION_H_INCLUDED)
245 #define DUK_EXCEPTION_H_INCLUDED
246 
247 #if defined(DUK_USE_CPP_EXCEPTIONS)
248 class duk_internal_exception {
249  /* intentionally empty */
250 };
251 #endif
252 
253 #endif /* DUK_EXCEPTION_H_INCLUDED */
254 /* #include duk_forwdecl.h */
255 /*
256  * Forward declarations for all Duktape structures.
257  */
258 
259 #if !defined(DUK_FORWDECL_H_INCLUDED)
260 #define DUK_FORWDECL_H_INCLUDED
261 
262 /*
263  * Forward declarations
264  */
265 
266 #if defined(DUK_USE_CPP_EXCEPTIONS)
267 class duk_internal_exception;
268 #else
269 struct duk_jmpbuf;
270 #endif
271 
272 /* duk_tval intentionally skipped */
273 struct duk_heaphdr;
274 struct duk_heaphdr_string;
275 struct duk_harray;
276 struct duk_hstring;
277 struct duk_hstring_external;
278 struct duk_hobject;
279 struct duk_hcompfunc;
280 struct duk_hnatfunc;
281 struct duk_hthread;
282 struct duk_hbufobj;
283 struct duk_hbuffer;
284 struct duk_hbuffer_fixed;
285 struct duk_hbuffer_dynamic;
286 struct duk_hbuffer_external;
287 
288 struct duk_propaccessor;
289 union duk_propvalue;
290 struct duk_propdesc;
291 
292 struct duk_heap;
293 struct duk_breakpoint;
294 
295 struct duk_activation;
296 struct duk_catcher;
297 struct duk_strcache;
298 struct duk_ljstate;
299 struct duk_strtab_entry;
300 
301 #if defined(DUK_USE_DEBUG)
302 struct duk_fixedbuffer;
303 #endif
304 
305 struct duk_bitdecoder_ctx;
306 struct duk_bitencoder_ctx;
307 struct duk_bufwriter_ctx;
308 
309 struct duk_token;
310 struct duk_re_token;
311 struct duk_lexer_point;
312 struct duk_lexer_ctx;
313 struct duk_lexer_codepoint;
314 
315 struct duk_compiler_instr;
316 struct duk_compiler_func;
317 struct duk_compiler_ctx;
318 
319 struct duk_re_matcher_ctx;
320 struct duk_re_compiler_ctx;
321 
322 #if defined(DUK_USE_CPP_EXCEPTIONS)
323 /* no typedef */
324 #else
325 typedef struct duk_jmpbuf duk_jmpbuf;
326 #endif
327 
328 /* duk_tval intentionally skipped */
329 typedef struct duk_heaphdr duk_heaphdr;
331 typedef struct duk_harray duk_harray;
332 typedef struct duk_hstring duk_hstring;
334 typedef struct duk_hobject duk_hobject;
335 typedef struct duk_hcompfunc duk_hcompfunc;
336 typedef struct duk_hnatfunc duk_hnatfunc;
337 typedef struct duk_hbufobj duk_hbufobj;
338 typedef struct duk_hthread duk_hthread;
339 typedef struct duk_hbuffer duk_hbuffer;
340 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
343 
344 typedef struct duk_propaccessor duk_propaccessor;
345 typedef union duk_propvalue duk_propvalue;
346 typedef struct duk_propdesc duk_propdesc;
347 
348 typedef struct duk_heap duk_heap;
349 typedef struct duk_breakpoint duk_breakpoint;
350 
351 typedef struct duk_activation duk_activation;
352 typedef struct duk_catcher duk_catcher;
353 typedef struct duk_strcache duk_strcache;
354 typedef struct duk_ljstate duk_ljstate;
355 typedef struct duk_strtab_entry duk_strtab_entry;
356 
357 #if defined(DUK_USE_DEBUG)
358 typedef struct duk_fixedbuffer duk_fixedbuffer;
359 #endif
360 
363 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
364 
365 typedef struct duk_token duk_token;
366 typedef struct duk_re_token duk_re_token;
367 typedef struct duk_lexer_point duk_lexer_point;
368 typedef struct duk_lexer_ctx duk_lexer_ctx;
370 
372 typedef struct duk_compiler_func duk_compiler_func;
373 typedef struct duk_compiler_ctx duk_compiler_ctx;
374 
377 
378 #endif /* DUK_FORWDECL_H_INCLUDED */
379 /* #include duk_tval.h */
380 /*
381  * Tagged type definition (duk_tval) and accessor macros.
382  *
383  * Access all fields through the accessor macros, as the representation
384  * is quite tricky.
385  *
386  * There are two packed type alternatives: an 8-byte representation
387  * based on an IEEE double (preferred for compactness), and a 12-byte
388  * representation (portability). The latter is needed also in e.g.
389  * 64-bit environments (it usually pads to 16 bytes per value).
390  *
391  * Selecting the tagged type format involves many trade-offs (memory
392  * use, size and performance of generated code, portability, etc).
393  *
394  * NB: because macro arguments are often expressions, macros should
395  * avoid evaluating their argument more than once.
396  */
397 
398 #if !defined(DUK_TVAL_H_INCLUDED)
399 #define DUK_TVAL_H_INCLUDED
400 
401 /* sanity */
402 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
403 #error unsupported: cannot determine byte order variant
404 #endif
405 
406 #if defined(DUK_USE_PACKED_TVAL)
407 /* ======================================================================== */
408 
409 /*
410  * Packed 8-byte representation
411  */
412 
413 /* use duk_double_union as duk_tval directly */
414 typedef union duk_double_union duk_tval;
415 typedef struct {
416  duk_uint16_t a;
417  duk_uint16_t b;
418  duk_uint16_t c;
419  duk_uint16_t d;
421 
422 /* tags */
423 #define DUK_TAG_NORMALIZED_NAN 0x7ff8UL /* the NaN variant we use */
424 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
425 #define DUK_TAG_MIN 0xfff1UL
426 #if defined(DUK_USE_FASTINT)
427 #define DUK_TAG_FASTINT 0xfff1UL /* embed: integer value */
428 #endif
429 #define DUK_TAG_UNUSED 0xfff2UL /* marker; not actual tagged value */
430 #define DUK_TAG_UNDEFINED 0xfff3UL /* embed: nothing */
431 #define DUK_TAG_NULL 0xfff4UL /* embed: nothing */
432 #define DUK_TAG_BOOLEAN 0xfff5UL /* embed: 0 or 1 (false or true) */
433 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
434 #define DUK_TAG_POINTER 0xfff6UL /* embed: void ptr */
435 #define DUK_TAG_LIGHTFUNC 0xfff7UL /* embed: func ptr */
436 #define DUK_TAG_STRING 0xfff8UL /* embed: duk_hstring ptr */
437 #define DUK_TAG_OBJECT 0xfff9UL /* embed: duk_hobject ptr */
438 #define DUK_TAG_BUFFER 0xfffaUL /* embed: duk_hbuffer ptr */
439 #define DUK_TAG_MAX 0xfffaUL
440 
441 /* for convenience */
442 #define DUK_XTAG_BOOLEAN_FALSE 0xfff50000UL
443 #define DUK_XTAG_BOOLEAN_TRUE 0xfff50001UL
444 
445 #define DUK_TVAL_IS_VALID_TAG(tv) \
446  (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
447 
448 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
449 #define DUK_TVAL_UNUSED_INITIALIZER() \
450  { DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
451 
452 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
453 #if defined(DUK_USE_64BIT_OPS)
454 #if defined(DUK_USE_DOUBLE_ME)
455 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
456  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
457  } while (0)
458 #else
459 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
460  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
461  } while (0)
462 #endif
463 #else /* DUK_USE_64BIT_OPS */
464 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag) do { \
465  duk_tval *duk__tv; \
466  duk__tv = (tv); \
467  duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
468  duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
469  } while (0)
470 #endif /* DUK_USE_64BIT_OPS */
471 
472 #if defined(DUK_USE_64BIT_OPS)
473 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
474 #if defined(DUK_USE_DOUBLE_ME)
475 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
476  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
477  ((duk_uint64_t) (flags)) | \
478  (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
479  } while (0)
480 #else
481 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
482  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
483  (((duk_uint64_t) (flags)) << 32) | \
484  ((duk_uint64_t) (duk_uint32_t) (fp)); \
485  } while (0)
486 #endif
487 #else /* DUK_USE_64BIT_OPS */
488 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
489  duk_tval *duk__tv; \
490  duk__tv = (tv); \
491  duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
492  duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
493  } while (0)
494 #endif /* DUK_USE_64BIT_OPS */
495 
496 #if defined(DUK_USE_FASTINT)
497 /* Note: masking is done for 'i' to deal with negative numbers correctly */
498 #if defined(DUK_USE_DOUBLE_ME)
499 #define DUK__TVAL_SET_I48(tv,i) do { \
500  duk_tval *duk__tv; \
501  duk__tv = (tv); \
502  duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
503  duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
504  } while (0)
505 #define DUK__TVAL_SET_U32(tv,i) do { \
506  duk_tval *duk__tv; \
507  duk__tv = (tv); \
508  duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
509  duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
510  } while (0)
511 #else
512 #define DUK__TVAL_SET_I48(tv,i) do { \
513  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & 0x0000ffffffffffffULL); \
514  } while (0)
515 #define DUK__TVAL_SET_U32(tv,i) do { \
516  (tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
517  } while (0)
518 #endif
519 
520 /* This needs to go through a cast because sign extension is needed. */
521 #define DUK__TVAL_SET_I32(tv,i) do { \
522  duk_int64_t duk__tmp = (duk_int64_t) (i); \
523  DUK_TVAL_SET_I48((tv), duk__tmp); \
524  } while (0)
525 
526 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
527 #if defined(DUK_USE_DOUBLE_ME)
528 #define DUK__TVAL_GET_FASTINT(tv) (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)
529 #else
530 #define DUK__TVAL_GET_FASTINT(tv) ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
531 #endif
532 #define DUK__TVAL_GET_FASTINT_U32(tv) ((tv)->ui[DUK_DBL_IDX_UI1])
533 #define DUK__TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
534 #endif /* DUK_USE_FASTINT */
535 
536 #define DUK_TVAL_SET_UNDEFINED(tv) do { \
537  (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
538  } while (0)
539 #define DUK_TVAL_SET_UNUSED(tv) do { \
540  (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
541  } while (0)
542 #define DUK_TVAL_SET_NULL(tv) do { \
543  (tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
544  } while (0)
545 
546 #define DUK_TVAL_SET_BOOLEAN(tv,val) DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
547 
548 #define DUK_TVAL_SET_NAN(tv) DUK_DBLUNION_SET_NAN_FULL((tv))
549 
550 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
551 #if defined(DUK_USE_FASTINT)
552 #define DUK_TVAL_SET_DOUBLE(tv,d) do { \
553  duk_double_t duk__dblval; \
554  duk__dblval = (d); \
555  DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
556  DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
557  } while (0)
558 #define DUK_TVAL_SET_I48(tv,i) DUK__TVAL_SET_I48((tv), (i))
559 #define DUK_TVAL_SET_I32(tv,i) DUK__TVAL_SET_I32((tv), (i))
560 #define DUK_TVAL_SET_U32(tv,i) DUK__TVAL_SET_U32((tv), (i))
561 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) duk_tval_set_number_chkfast_fast((tv), (d))
562 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) duk_tval_set_number_chkfast_slow((tv), (d))
563 #define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
564 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
565  duk_tval *duk__tv; \
566  duk_double_t duk__d; \
567  duk__tv = (tv); \
568  if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
569  duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
570  DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
571  } \
572  } while (0)
573 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
574  duk_tval *duk__tv; \
575  duk_double_t duk__d; \
576  duk__tv = (tv); \
577  if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
578  duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
579  DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
580  } \
581  } while (0)
582 #else /* DUK_USE_FASTINT */
583 #define DUK_TVAL_SET_DOUBLE(tv,d) do { \
584  duk_double_t duk__dblval; \
585  duk__dblval = (d); \
586  DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
587  DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
588  } while (0)
589 #define DUK_TVAL_SET_I48(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */
590 #define DUK_TVAL_SET_I32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
591 #define DUK_TVAL_SET_U32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
592 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
593 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
594 #define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
595 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
596 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
597 #endif /* DUK_USE_FASTINT */
598 
599 #define DUK_TVAL_SET_FASTINT(tv,i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
600 
601 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
602 #define DUK_TVAL_SET_STRING(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
603 #define DUK_TVAL_SET_OBJECT(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
604 #define DUK_TVAL_SET_BUFFER(tv,h) DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
605 #define DUK_TVAL_SET_POINTER(tv,p) DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
606 
607 #define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0)
608 
609 /* getters */
610 #define DUK_TVAL_GET_BOOLEAN(tv) ((duk_small_int_t) (tv)->us[DUK_DBL_IDX_US1])
611 #if defined(DUK_USE_FASTINT)
612 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
613 #define DUK_TVAL_GET_FASTINT(tv) DUK__TVAL_GET_FASTINT((tv))
614 #define DUK_TVAL_GET_FASTINT_U32(tv) DUK__TVAL_GET_FASTINT_U32((tv))
615 #define DUK_TVAL_GET_FASTINT_I32(tv) DUK__TVAL_GET_FASTINT_I32((tv))
616 #define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_packed((tv))
617 #else
618 #define DUK_TVAL_GET_NUMBER(tv) ((tv)->d)
619 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->d)
620 #endif
621 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
622  (out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
623  (out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
624  } while (0)
625 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
626 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) (((duk_small_int_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
627 #define DUK_TVAL_GET_STRING(tv) ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
628 #define DUK_TVAL_GET_OBJECT(tv) ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
629 #define DUK_TVAL_GET_BUFFER(tv) ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
630 #define DUK_TVAL_GET_POINTER(tv) ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
631 #define DUK_TVAL_GET_HEAPHDR(tv) ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
632 
633 /* decoding */
634 #define DUK_TVAL_GET_TAG(tv) ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
635 
636 #define DUK_TVAL_IS_UNDEFINED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
637 #define DUK_TVAL_IS_UNUSED(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
638 #define DUK_TVAL_IS_NULL(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
639 #define DUK_TVAL_IS_BOOLEAN(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
640 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
641 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv) ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
642 #define DUK_TVAL_IS_LIGHTFUNC(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
643 #define DUK_TVAL_IS_STRING(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
644 #define DUK_TVAL_IS_OBJECT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
645 #define DUK_TVAL_IS_BUFFER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
646 #define DUK_TVAL_IS_POINTER(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
647 #if defined(DUK_USE_FASTINT)
648 /* 0xfff0 is -Infinity */
649 #define DUK_TVAL_IS_DOUBLE(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
650 #define DUK_TVAL_IS_FASTINT(tv) (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
651 #define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
652 #else
653 #define DUK_TVAL_IS_NUMBER(tv) (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
654 #define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
655 #endif
656 
657 /* This is performance critical because it appears in every DECREF. */
658 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
659 
660 #if defined(DUK_USE_FASTINT)
661 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
662 #endif
663 
664 #else /* DUK_USE_PACKED_TVAL */
665 /* ======================================================================== */
666 
667 /*
668  * Portable 12-byte representation
669  */
670 
671 /* Note: not initializing all bytes is normally not an issue: Duktape won't
672  * read or use the uninitialized bytes so valgrind won't issue warnings.
673  * In some special cases a harmless valgrind warning may be issued though.
674  * For example, the DumpHeap debugger command writes out a compiled function's
675  * 'data' area as is, including any uninitialized bytes, which causes a
676  * valgrind warning.
677  */
678 
679 typedef struct duk_tval_struct duk_tval;
680 
681 struct duk_tval_struct {
682  duk_small_uint_t t;
683  duk_small_uint_t v_extra;
684  union {
685  duk_double_t d;
686  duk_small_int_t i;
687 #if defined(DUK_USE_FASTINT)
688  duk_int64_t fi; /* if present, forces 16-byte duk_tval */
689 #endif
690  void *voidptr;
691  duk_hstring *hstring;
692  duk_hobject *hobject;
693  duk_hcompfunc *hcompfunc;
694  duk_hnatfunc *hnatfunc;
695  duk_hthread *hthread;
696  duk_hbuffer *hbuffer;
697  duk_heaphdr *heaphdr;
698  duk_c_function lightfunc;
699  } v;
700 };
701 
702 typedef struct {
703  duk_small_uint_t t;
704  duk_small_uint_t v_extra;
705  /* The rest of the fields don't matter except for debug dumps and such
706  * for which a partial initializer may trigger out-ot-bounds memory
707  * reads. Include a double field which is usually as large or larger
708  * than pointers (not always however).
709  */
710  duk_double_t d;
712 
713 #define DUK_TVAL_UNUSED_INITIALIZER() \
714  { DUK_TAG_UNUSED, 0, 0.0 }
715 
716 #define DUK_TAG_MIN 0
717 #define DUK_TAG_NUMBER 0 /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
718 #if defined(DUK_USE_FASTINT)
719 #define DUK_TAG_FASTINT 1
720 #endif
721 #define DUK_TAG_UNDEFINED 2
722 #define DUK_TAG_NULL 3
723 #define DUK_TAG_BOOLEAN 4
724 #define DUK_TAG_POINTER 5
725 #define DUK_TAG_LIGHTFUNC 6
726 #define DUK_TAG_UNUSED 7 /* marker; not actual tagged type */
727 #define DUK_TAG_STRING 8 /* first heap allocated, match bit boundary */
728 #define DUK_TAG_OBJECT 9
729 #define DUK_TAG_BUFFER 10
730 #define DUK_TAG_MAX 10
731 
732 #define DUK_TVAL_IS_VALID_TAG(tv) \
733  (DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
734 
735 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
736  * to support the 8-byte representation. Further, it is a non-heap-allocated
737  * type so it should come before DUK_TAG_STRING. Finally, it should not break
738  * the tag value ranges covered by case-clauses in a switch-case.
739  */
740 
741 /* setters */
742 #define DUK_TVAL_SET_UNDEFINED(tv) do { \
743  duk_tval *duk__tv; \
744  duk__tv = (tv); \
745  duk__tv->t = DUK_TAG_UNDEFINED; \
746  } while (0)
747 
748 #define DUK_TVAL_SET_UNUSED(tv) do { \
749  duk_tval *duk__tv; \
750  duk__tv = (tv); \
751  duk__tv->t = DUK_TAG_UNUSED; \
752  } while (0)
753 
754 #define DUK_TVAL_SET_NULL(tv) do { \
755  duk_tval *duk__tv; \
756  duk__tv = (tv); \
757  duk__tv->t = DUK_TAG_NULL; \
758  } while (0)
759 
760 #define DUK_TVAL_SET_BOOLEAN(tv,val) do { \
761  duk_tval *duk__tv; \
762  duk__tv = (tv); \
763  duk__tv->t = DUK_TAG_BOOLEAN; \
764  duk__tv->v.i = (val); \
765  } while (0)
766 
767 #if defined(DUK_USE_FASTINT)
768 #define DUK_TVAL_SET_DOUBLE(tv,val) do { \
769  duk_tval *duk__tv; \
770  duk_double_t duk__dblval; \
771  duk__dblval = (val); \
772  DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
773  duk__tv = (tv); \
774  duk__tv->t = DUK_TAG_NUMBER; \
775  duk__tv->v.d = duk__dblval; \
776  } while (0)
777 #define DUK_TVAL_SET_I48(tv,val) do { \
778  duk_tval *duk__tv; \
779  duk__tv = (tv); \
780  duk__tv->t = DUK_TAG_FASTINT; \
781  duk__tv->v.fi = (val); \
782  } while (0)
783 #define DUK_TVAL_SET_U32(tv,val) do { \
784  duk_tval *duk__tv; \
785  duk__tv = (tv); \
786  duk__tv->t = DUK_TAG_FASTINT; \
787  duk__tv->v.fi = (duk_int64_t) (val); \
788  } while (0)
789 #define DUK_TVAL_SET_I32(tv,val) do { \
790  duk_tval *duk__tv; \
791  duk__tv = (tv); \
792  duk__tv->t = DUK_TAG_FASTINT; \
793  duk__tv->v.fi = (duk_int64_t) (val); \
794  } while (0)
795 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
796  duk_tval_set_number_chkfast_fast((tv), (d))
797 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
798  duk_tval_set_number_chkfast_slow((tv), (d))
799 #define DUK_TVAL_SET_NUMBER(tv,val) \
800  DUK_TVAL_SET_DOUBLE((tv), (val))
801 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
802  duk_tval *duk__tv; \
803  duk_double_t duk__d; \
804  duk__tv = (tv); \
805  if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
806  duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
807  DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
808  } \
809  } while (0)
810 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
811  duk_tval *duk__tv; \
812  duk_double_t duk__d; \
813  duk__tv = (tv); \
814  if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
815  duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
816  DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
817  } \
818  } while (0)
819 #else /* DUK_USE_FASTINT */
820 #define DUK_TVAL_SET_DOUBLE(tv,d) \
821  DUK_TVAL_SET_NUMBER((tv), (d))
822 #define DUK_TVAL_SET_I48(tv,val) \
823  DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val)) /* XXX: fast int-to-double */
824 #define DUK_TVAL_SET_U32(tv,val) \
825  DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
826 #define DUK_TVAL_SET_I32(tv,val) \
827  DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
828 #define DUK_TVAL_SET_NUMBER(tv,val) do { \
829  duk_tval *duk__tv; \
830  duk_double_t duk__dblval; \
831  duk__dblval = (val); \
832  DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
833  duk__tv = (tv); \
834  duk__tv->t = DUK_TAG_NUMBER; \
835  duk__tv->v.d = duk__dblval; \
836  } while (0)
837 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
838  DUK_TVAL_SET_NUMBER((tv), (d))
839 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
840  DUK_TVAL_SET_NUMBER((tv), (d))
841 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
842 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
843 #endif /* DUK_USE_FASTINT */
844 
845 #define DUK_TVAL_SET_FASTINT(tv,i) \
846  DUK_TVAL_SET_I48((tv), (i)) /* alias */
847 
848 #define DUK_TVAL_SET_POINTER(tv,hptr) do { \
849  duk_tval *duk__tv; \
850  duk__tv = (tv); \
851  duk__tv->t = DUK_TAG_POINTER; \
852  duk__tv->v.voidptr = (hptr); \
853  } while (0)
854 
855 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags) do { \
856  duk_tval *duk__tv; \
857  duk__tv = (tv); \
858  duk__tv->t = DUK_TAG_LIGHTFUNC; \
859  duk__tv->v_extra = (flags); \
860  duk__tv->v.lightfunc = (duk_c_function) (fp); \
861  } while (0)
862 
863 #define DUK_TVAL_SET_STRING(tv,hptr) do { \
864  duk_tval *duk__tv; \
865  duk__tv = (tv); \
866  duk__tv->t = DUK_TAG_STRING; \
867  duk__tv->v.hstring = (hptr); \
868  } while (0)
869 
870 #define DUK_TVAL_SET_OBJECT(tv,hptr) do { \
871  duk_tval *duk__tv; \
872  duk__tv = (tv); \
873  duk__tv->t = DUK_TAG_OBJECT; \
874  duk__tv->v.hobject = (hptr); \
875  } while (0)
876 
877 #define DUK_TVAL_SET_BUFFER(tv,hptr) do { \
878  duk_tval *duk__tv; \
879  duk__tv = (tv); \
880  duk__tv->t = DUK_TAG_BUFFER; \
881  duk__tv->v.hbuffer = (hptr); \
882  } while (0)
883 
884 #define DUK_TVAL_SET_NAN(tv) do { \
885  /* in non-packed representation we don't care about which NaN is used */ \
886  duk_tval *duk__tv; \
887  duk__tv = (tv); \
888  duk__tv->t = DUK_TAG_NUMBER; \
889  duk__tv->v.d = DUK_DOUBLE_NAN; \
890  } while (0)
891 
892 #define DUK_TVAL_SET_TVAL(tv,x) do { *(tv) = *(x); } while (0)
893 
894 /* getters */
895 #define DUK_TVAL_GET_BOOLEAN(tv) ((tv)->v.i)
896 #if defined(DUK_USE_FASTINT)
897 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
898 #define DUK_TVAL_GET_FASTINT(tv) ((tv)->v.fi)
899 #define DUK_TVAL_GET_FASTINT_U32(tv) ((duk_uint32_t) ((tv)->v.fi))
900 #define DUK_TVAL_GET_FASTINT_I32(tv) ((duk_int32_t) ((tv)->v.fi))
901 #if 0
902 #define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
903  (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
904  DUK_TVAL_GET_DOUBLE((tv)))
905 #define DUK_TVAL_GET_NUMBER(tv) duk_tval_get_number_unpacked((tv))
906 #else
907 /* This seems reasonable overall. */
908 #define DUK_TVAL_GET_NUMBER(tv) (DUK_TVAL_IS_FASTINT((tv)) ? \
909  duk_tval_get_number_unpacked_fastint((tv)) : \
910  DUK_TVAL_GET_DOUBLE((tv)))
911 #endif
912 #else
913 #define DUK_TVAL_GET_NUMBER(tv) ((tv)->v.d)
914 #define DUK_TVAL_GET_DOUBLE(tv) ((tv)->v.d)
915 #endif /* DUK_USE_FASTINT */
916 #define DUK_TVAL_GET_POINTER(tv) ((tv)->v.voidptr)
917 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags) do { \
918  (out_flags) = (duk_uint32_t) (tv)->v_extra; \
919  (out_fp) = (tv)->v.lightfunc; \
920  } while (0)
921 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
922 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv) ((duk_uint32_t) ((tv)->v_extra))
923 #define DUK_TVAL_GET_STRING(tv) ((tv)->v.hstring)
924 #define DUK_TVAL_GET_OBJECT(tv) ((tv)->v.hobject)
925 #define DUK_TVAL_GET_BUFFER(tv) ((tv)->v.hbuffer)
926 #define DUK_TVAL_GET_HEAPHDR(tv) ((tv)->v.heaphdr)
927 
928 /* decoding */
929 #define DUK_TVAL_GET_TAG(tv) ((tv)->t)
930 #define DUK_TVAL_IS_UNDEFINED(tv) ((tv)->t == DUK_TAG_UNDEFINED)
931 #define DUK_TVAL_IS_UNUSED(tv) ((tv)->t == DUK_TAG_UNUSED)
932 #define DUK_TVAL_IS_NULL(tv) ((tv)->t == DUK_TAG_NULL)
933 #define DUK_TVAL_IS_BOOLEAN(tv) ((tv)->t == DUK_TAG_BOOLEAN)
934 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
935 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv) (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
936 #if defined(DUK_USE_FASTINT)
937 #define DUK_TVAL_IS_DOUBLE(tv) ((tv)->t == DUK_TAG_NUMBER)
938 #define DUK_TVAL_IS_FASTINT(tv) ((tv)->t == DUK_TAG_FASTINT)
939 #define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER || \
940  (tv)->t == DUK_TAG_FASTINT)
941 #else
942 #define DUK_TVAL_IS_NUMBER(tv) ((tv)->t == DUK_TAG_NUMBER)
943 #define DUK_TVAL_IS_DOUBLE(tv) DUK_TVAL_IS_NUMBER((tv))
944 #endif /* DUK_USE_FASTINT */
945 #define DUK_TVAL_IS_POINTER(tv) ((tv)->t == DUK_TAG_POINTER)
946 #define DUK_TVAL_IS_LIGHTFUNC(tv) ((tv)->t == DUK_TAG_LIGHTFUNC)
947 #define DUK_TVAL_IS_STRING(tv) ((tv)->t == DUK_TAG_STRING)
948 #define DUK_TVAL_IS_OBJECT(tv) ((tv)->t == DUK_TAG_OBJECT)
949 #define DUK_TVAL_IS_BUFFER(tv) ((tv)->t == DUK_TAG_BUFFER)
950 
951 /* This is performance critical because it's needed for every DECREF.
952  * Take advantage of the fact that the first heap allocated tag is 8,
953  * so that bit 3 is set for all heap allocated tags (and never set for
954  * non-heap-allocated tags).
955  */
956 #if 0
957 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t >= DUK_TAG_STRING)
958 #endif
959 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv) ((tv)->t & 0x08)
960 
961 #if defined(DUK_USE_FASTINT)
962 #if 0
963 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
964 #endif
965 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
966 #endif
967 
968 #endif /* DUK_USE_PACKED_TVAL */
969 
970 /*
971  * Convenience (independent of representation)
972  */
973 
974 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv) DUK_TVAL_SET_BOOLEAN((tv), 1)
975 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv) DUK_TVAL_SET_BOOLEAN((tv), 0)
976 
977 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
978  DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
979 
980 /* Lightfunc flags packing and unpacking. */
981 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
982  * Avoid signed shifts due to portability limitations.
983  */
984 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
985  ((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
986 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
987  (((lf_flags) >> 4) & 0x0f)
988 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
989  ((lf_flags) & 0x0f)
990 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
991  (((magic) & 0xff) << 8) | ((length) << 4) | (nargs)
992 
993 #define DUK_LFUNC_NARGS_VARARGS 0x0f /* varargs marker */
994 #define DUK_LFUNC_NARGS_MIN 0x00
995 #define DUK_LFUNC_NARGS_MAX 0x0e /* max, excl. varargs marker */
996 #define DUK_LFUNC_LENGTH_MIN 0x00
997 #define DUK_LFUNC_LENGTH_MAX 0x0f
998 #define DUK_LFUNC_MAGIC_MIN (-0x80)
999 #define DUK_LFUNC_MAGIC_MAX 0x7f
1000 
1001 /* fastint constants etc */
1002 #if defined(DUK_USE_FASTINT)
1003 #define DUK_FASTINT_MIN (-0x800000000000LL)
1004 #define DUK_FASTINT_MAX 0x7fffffffffffLL
1005 #define DUK_FASTINT_BITS 48
1006 
1007 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1008 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1009 #endif
1010 
1011 #endif /* DUK_TVAL_H_INCLUDED */
1012 /* #include duk_builtins.h */
1013 /*
1014  * Automatically generated by genbuiltins.py, do not edit!
1015  */
1016 
1017 #if !defined(DUK_BUILTINS_H_INCLUDED)
1018 #define DUK_BUILTINS_H_INCLUDED
1019 
1020 #if defined(DUK_USE_ROM_STRINGS)
1021 #error ROM support not enabled, rerun configure.py with --rom-support
1022 #else /* DUK_USE_ROM_STRINGS */
1023 #define DUK_STRIDX_UC_UNDEFINED 0 /* 'Undefined' */
1024 #define DUK_HEAP_STRING_UC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1025 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1026 #define DUK_STRIDX_UC_NULL 1 /* 'Null' */
1027 #define DUK_HEAP_STRING_UC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1028 #define DUK_HTHREAD_STRING_UC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1029 #define DUK_STRIDX_UC_SYMBOL 2 /* 'Symbol' */
1030 #define DUK_HEAP_STRING_UC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1031 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1032 #define DUK_STRIDX_UC_ARGUMENTS 3 /* 'Arguments' */
1033 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1034 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1035 #define DUK_STRIDX_UC_OBJECT 4 /* 'Object' */
1036 #define DUK_HEAP_STRING_UC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1037 #define DUK_HTHREAD_STRING_UC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1038 #define DUK_STRIDX_UC_FUNCTION 5 /* 'Function' */
1039 #define DUK_HEAP_STRING_UC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1040 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1041 #define DUK_STRIDX_ARRAY 6 /* 'Array' */
1042 #define DUK_HEAP_STRING_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
1043 #define DUK_HTHREAD_STRING_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
1044 #define DUK_STRIDX_UC_STRING 7 /* 'String' */
1045 #define DUK_HEAP_STRING_UC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1046 #define DUK_HTHREAD_STRING_UC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1047 #define DUK_STRIDX_UC_BOOLEAN 8 /* 'Boolean' */
1048 #define DUK_HEAP_STRING_UC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1049 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1050 #define DUK_STRIDX_UC_NUMBER 9 /* 'Number' */
1051 #define DUK_HEAP_STRING_UC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1052 #define DUK_HTHREAD_STRING_UC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1053 #define DUK_STRIDX_DATE 10 /* 'Date' */
1054 #define DUK_HEAP_STRING_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
1055 #define DUK_HTHREAD_STRING_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
1056 #define DUK_STRIDX_REG_EXP 11 /* 'RegExp' */
1057 #define DUK_HEAP_STRING_REG_EXP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1058 #define DUK_HTHREAD_STRING_REG_EXP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1059 #define DUK_STRIDX_UC_ERROR 12 /* 'Error' */
1060 #define DUK_HEAP_STRING_UC_ERROR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1061 #define DUK_HTHREAD_STRING_UC_ERROR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1062 #define DUK_STRIDX_MATH 13 /* 'Math' */
1063 #define DUK_HEAP_STRING_MATH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1064 #define DUK_HTHREAD_STRING_MATH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1065 #define DUK_STRIDX_JSON 14 /* 'JSON' */
1066 #define DUK_HEAP_STRING_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1067 #define DUK_HTHREAD_STRING_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1068 #define DUK_STRIDX_EMPTY_STRING 15 /* '' */
1069 #define DUK_HEAP_STRING_EMPTY_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1070 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1071 #define DUK_STRIDX_ARRAY_BUFFER 16 /* 'ArrayBuffer' */
1072 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1073 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1074 #define DUK_STRIDX_DATA_VIEW 17 /* 'DataView' */
1075 #define DUK_HEAP_STRING_DATA_VIEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1076 #define DUK_HTHREAD_STRING_DATA_VIEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1077 #define DUK_STRIDX_INT8_ARRAY 18 /* 'Int8Array' */
1078 #define DUK_HEAP_STRING_INT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1079 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1080 #define DUK_STRIDX_UINT8_ARRAY 19 /* 'Uint8Array' */
1081 #define DUK_HEAP_STRING_UINT8_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1082 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1083 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY 20 /* 'Uint8ClampedArray' */
1084 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1085 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1086 #define DUK_STRIDX_INT16_ARRAY 21 /* 'Int16Array' */
1087 #define DUK_HEAP_STRING_INT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1088 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1089 #define DUK_STRIDX_UINT16_ARRAY 22 /* 'Uint16Array' */
1090 #define DUK_HEAP_STRING_UINT16_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1091 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1092 #define DUK_STRIDX_INT32_ARRAY 23 /* 'Int32Array' */
1093 #define DUK_HEAP_STRING_INT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1094 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1095 #define DUK_STRIDX_UINT32_ARRAY 24 /* 'Uint32Array' */
1096 #define DUK_HEAP_STRING_UINT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1097 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1098 #define DUK_STRIDX_FLOAT32_ARRAY 25 /* 'Float32Array' */
1099 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1100 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1101 #define DUK_STRIDX_FLOAT64_ARRAY 26 /* 'Float64Array' */
1102 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1103 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1104 #define DUK_STRIDX_GLOBAL 27 /* 'global' */
1105 #define DUK_HEAP_STRING_GLOBAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1106 #define DUK_HTHREAD_STRING_GLOBAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1107 #define DUK_STRIDX_OBJ_ENV 28 /* 'ObjEnv' */
1108 #define DUK_HEAP_STRING_OBJ_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1109 #define DUK_HTHREAD_STRING_OBJ_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1110 #define DUK_STRIDX_DEC_ENV 29 /* 'DecEnv' */
1111 #define DUK_HEAP_STRING_DEC_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1112 #define DUK_HTHREAD_STRING_DEC_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1113 #define DUK_STRIDX_UC_BUFFER 30 /* 'Buffer' */
1114 #define DUK_HEAP_STRING_UC_BUFFER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1115 #define DUK_HTHREAD_STRING_UC_BUFFER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1116 #define DUK_STRIDX_UC_POINTER 31 /* 'Pointer' */
1117 #define DUK_HEAP_STRING_UC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1118 #define DUK_HTHREAD_STRING_UC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1119 #define DUK_STRIDX_UC_THREAD 32 /* 'Thread' */
1120 #define DUK_HEAP_STRING_UC_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1121 #define DUK_HTHREAD_STRING_UC_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1122 #define DUK_STRIDX_EVAL 33 /* 'eval' */
1123 #define DUK_HEAP_STRING_EVAL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1124 #define DUK_HTHREAD_STRING_EVAL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1125 #define DUK_STRIDX_VALUE 34 /* 'value' */
1126 #define DUK_HEAP_STRING_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1127 #define DUK_HTHREAD_STRING_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1128 #define DUK_STRIDX_WRITABLE 35 /* 'writable' */
1129 #define DUK_HEAP_STRING_WRITABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1130 #define DUK_HTHREAD_STRING_WRITABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1131 #define DUK_STRIDX_CONFIGURABLE 36 /* 'configurable' */
1132 #define DUK_HEAP_STRING_CONFIGURABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1133 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1134 #define DUK_STRIDX_ENUMERABLE 37 /* 'enumerable' */
1135 #define DUK_HEAP_STRING_ENUMERABLE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1136 #define DUK_HTHREAD_STRING_ENUMERABLE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1137 #define DUK_STRIDX_JOIN 38 /* 'join' */
1138 #define DUK_HEAP_STRING_JOIN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1139 #define DUK_HTHREAD_STRING_JOIN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1140 #define DUK_STRIDX_TO_LOCALE_STRING 39 /* 'toLocaleString' */
1141 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1142 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1143 #define DUK_STRIDX_VALUE_OF 40 /* 'valueOf' */
1144 #define DUK_HEAP_STRING_VALUE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1145 #define DUK_HTHREAD_STRING_VALUE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1146 #define DUK_STRIDX_TO_UTC_STRING 41 /* 'toUTCString' */
1147 #define DUK_HEAP_STRING_TO_UTC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1148 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1149 #define DUK_STRIDX_TO_ISO_STRING 42 /* 'toISOString' */
1150 #define DUK_HEAP_STRING_TO_ISO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1151 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1152 #define DUK_STRIDX_TO_GMT_STRING 43 /* 'toGMTString' */
1153 #define DUK_HEAP_STRING_TO_GMT_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1154 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1155 #define DUK_STRIDX_SOURCE 44 /* 'source' */
1156 #define DUK_HEAP_STRING_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1157 #define DUK_HTHREAD_STRING_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1158 #define DUK_STRIDX_IGNORE_CASE 45 /* 'ignoreCase' */
1159 #define DUK_HEAP_STRING_IGNORE_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1160 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1161 #define DUK_STRIDX_MULTILINE 46 /* 'multiline' */
1162 #define DUK_HEAP_STRING_MULTILINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1163 #define DUK_HTHREAD_STRING_MULTILINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1164 #define DUK_STRIDX_LAST_INDEX 47 /* 'lastIndex' */
1165 #define DUK_HEAP_STRING_LAST_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1166 #define DUK_HTHREAD_STRING_LAST_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1167 #define DUK_STRIDX_FLAGS 48 /* 'flags' */
1168 #define DUK_HEAP_STRING_FLAGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1169 #define DUK_HTHREAD_STRING_FLAGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1170 #define DUK_STRIDX_INDEX 49 /* 'index' */
1171 #define DUK_HEAP_STRING_INDEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1172 #define DUK_HTHREAD_STRING_INDEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1173 #define DUK_STRIDX_PROTOTYPE 50 /* 'prototype' */
1174 #define DUK_HEAP_STRING_PROTOTYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1175 #define DUK_HTHREAD_STRING_PROTOTYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1176 #define DUK_STRIDX_CONSTRUCTOR 51 /* 'constructor' */
1177 #define DUK_HEAP_STRING_CONSTRUCTOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1178 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1179 #define DUK_STRIDX_MESSAGE 52 /* 'message' */
1180 #define DUK_HEAP_STRING_MESSAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1181 #define DUK_HTHREAD_STRING_MESSAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1182 #define DUK_STRIDX_LC_BOOLEAN 53 /* 'boolean' */
1183 #define DUK_HEAP_STRING_LC_BOOLEAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1184 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1185 #define DUK_STRIDX_LC_NUMBER 54 /* 'number' */
1186 #define DUK_HEAP_STRING_LC_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1187 #define DUK_HTHREAD_STRING_LC_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1188 #define DUK_STRIDX_LC_STRING 55 /* 'string' */
1189 #define DUK_HEAP_STRING_LC_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1190 #define DUK_HTHREAD_STRING_LC_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1191 #define DUK_STRIDX_LC_SYMBOL 56 /* 'symbol' */
1192 #define DUK_HEAP_STRING_LC_SYMBOL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1193 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1194 #define DUK_STRIDX_LC_OBJECT 57 /* 'object' */
1195 #define DUK_HEAP_STRING_LC_OBJECT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1196 #define DUK_HTHREAD_STRING_LC_OBJECT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1197 #define DUK_STRIDX_LC_UNDEFINED 58 /* 'undefined' */
1198 #define DUK_HEAP_STRING_LC_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1199 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1200 #define DUK_STRIDX_NAN 59 /* 'NaN' */
1201 #define DUK_HEAP_STRING_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1202 #define DUK_HTHREAD_STRING_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1203 #define DUK_STRIDX_INFINITY 60 /* 'Infinity' */
1204 #define DUK_HEAP_STRING_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1205 #define DUK_HTHREAD_STRING_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1206 #define DUK_STRIDX_MINUS_INFINITY 61 /* '-Infinity' */
1207 #define DUK_HEAP_STRING_MINUS_INFINITY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1208 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1209 #define DUK_STRIDX_MINUS_ZERO 62 /* '-0' */
1210 #define DUK_HEAP_STRING_MINUS_ZERO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1211 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1212 #define DUK_STRIDX_COMMA 63 /* ',' */
1213 #define DUK_HEAP_STRING_COMMA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1214 #define DUK_HTHREAD_STRING_COMMA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1215 #define DUK_STRIDX_NEWLINE_4SPACE 64 /* '\n ' */
1216 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1217 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1218 #define DUK_STRIDX_BRACKETED_ELLIPSIS 65 /* '[...]' */
1219 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1220 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1221 #define DUK_STRIDX_INVALID_DATE 66 /* 'Invalid Date' */
1222 #define DUK_HEAP_STRING_INVALID_DATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1223 #define DUK_HTHREAD_STRING_INVALID_DATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1224 #define DUK_STRIDX_LC_ARGUMENTS 67 /* 'arguments' */
1225 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1226 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1227 #define DUK_STRIDX_CALLEE 68 /* 'callee' */
1228 #define DUK_HEAP_STRING_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1229 #define DUK_HTHREAD_STRING_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1230 #define DUK_STRIDX_CALLER 69 /* 'caller' */
1231 #define DUK_HEAP_STRING_CALLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1232 #define DUK_HTHREAD_STRING_CALLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1233 #define DUK_STRIDX_DELETE_PROPERTY 70 /* 'deleteProperty' */
1234 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1235 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1236 #define DUK_STRIDX_GET 71 /* 'get' */
1237 #define DUK_HEAP_STRING_GET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1238 #define DUK_HTHREAD_STRING_GET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1239 #define DUK_STRIDX_HAS 72 /* 'has' */
1240 #define DUK_HEAP_STRING_HAS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1241 #define DUK_HTHREAD_STRING_HAS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1242 #define DUK_STRIDX_OWN_KEYS 73 /* 'ownKeys' */
1243 #define DUK_HEAP_STRING_OWN_KEYS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1244 #define DUK_HTHREAD_STRING_OWN_KEYS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1245 #define DUK_STRIDX_SET_PROTOTYPE_OF 74 /* 'setPrototypeOf' */
1246 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1247 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1248 #define DUK_STRIDX___PROTO__ 75 /* '__proto__' */
1249 #define DUK_HEAP_STRING___PROTO__(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1250 #define DUK_HTHREAD_STRING___PROTO__(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1251 #define DUK_STRIDX_TO_STRING 76 /* 'toString' */
1252 #define DUK_HEAP_STRING_TO_STRING(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1253 #define DUK_HTHREAD_STRING_TO_STRING(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1254 #define DUK_STRIDX_TO_JSON 77 /* 'toJSON' */
1255 #define DUK_HEAP_STRING_TO_JSON(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1256 #define DUK_HTHREAD_STRING_TO_JSON(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1257 #define DUK_STRIDX_TYPE 78 /* 'type' */
1258 #define DUK_HEAP_STRING_TYPE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1259 #define DUK_HTHREAD_STRING_TYPE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1260 #define DUK_STRIDX_DATA 79 /* 'data' */
1261 #define DUK_HEAP_STRING_DATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1262 #define DUK_HTHREAD_STRING_DATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1263 #define DUK_STRIDX_LENGTH 80 /* 'length' */
1264 #define DUK_HEAP_STRING_LENGTH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1265 #define DUK_HTHREAD_STRING_LENGTH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1266 #define DUK_STRIDX_SET 81 /* 'set' */
1267 #define DUK_HEAP_STRING_SET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1268 #define DUK_HTHREAD_STRING_SET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1269 #define DUK_STRIDX_STACK 82 /* 'stack' */
1270 #define DUK_HEAP_STRING_STACK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1271 #define DUK_HTHREAD_STRING_STACK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1272 #define DUK_STRIDX_PC 83 /* 'pc' */
1273 #define DUK_HEAP_STRING_PC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1274 #define DUK_HTHREAD_STRING_PC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1275 #define DUK_STRIDX_LINE_NUMBER 84 /* 'lineNumber' */
1276 #define DUK_HEAP_STRING_LINE_NUMBER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1277 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1278 #define DUK_STRIDX_INT_TRACEDATA 85 /* '\xffTracedata' */
1279 #define DUK_HEAP_STRING_INT_TRACEDATA(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1280 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1281 #define DUK_STRIDX_NAME 86 /* 'name' */
1282 #define DUK_HEAP_STRING_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1283 #define DUK_HTHREAD_STRING_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1284 #define DUK_STRIDX_FILE_NAME 87 /* 'fileName' */
1285 #define DUK_HEAP_STRING_FILE_NAME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1286 #define DUK_HTHREAD_STRING_FILE_NAME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1287 #define DUK_STRIDX_LC_POINTER 88 /* 'pointer' */
1288 #define DUK_HEAP_STRING_LC_POINTER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1289 #define DUK_HTHREAD_STRING_LC_POINTER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1290 #define DUK_STRIDX_INT_VALUE 89 /* '\xffValue' */
1291 #define DUK_HEAP_STRING_INT_VALUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1292 #define DUK_HTHREAD_STRING_INT_VALUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1293 #define DUK_STRIDX_INT_NEXT 90 /* '\xffNext' */
1294 #define DUK_HEAP_STRING_INT_NEXT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1295 #define DUK_HTHREAD_STRING_INT_NEXT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1296 #define DUK_STRIDX_INT_BYTECODE 91 /* '\xffBytecode' */
1297 #define DUK_HEAP_STRING_INT_BYTECODE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1298 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1299 #define DUK_STRIDX_INT_FORMALS 92 /* '\xffFormals' */
1300 #define DUK_HEAP_STRING_INT_FORMALS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1301 #define DUK_HTHREAD_STRING_INT_FORMALS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1302 #define DUK_STRIDX_INT_VARMAP 93 /* '\xffVarmap' */
1303 #define DUK_HEAP_STRING_INT_VARMAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1304 #define DUK_HTHREAD_STRING_INT_VARMAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1305 #define DUK_STRIDX_INT_SOURCE 94 /* '\xffSource' */
1306 #define DUK_HEAP_STRING_INT_SOURCE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1307 #define DUK_HTHREAD_STRING_INT_SOURCE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1308 #define DUK_STRIDX_INT_PC2LINE 95 /* '\xffPc2line' */
1309 #define DUK_HEAP_STRING_INT_PC2LINE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1310 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1311 #define DUK_STRIDX_INT_ARGS 96 /* '\xffArgs' */
1312 #define DUK_HEAP_STRING_INT_ARGS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_ARGS)
1313 #define DUK_HTHREAD_STRING_INT_ARGS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_ARGS)
1314 #define DUK_STRIDX_INT_MAP 97 /* '\xffMap' */
1315 #define DUK_HEAP_STRING_INT_MAP(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1316 #define DUK_HTHREAD_STRING_INT_MAP(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1317 #define DUK_STRIDX_INT_VARENV 98 /* '\xffVarenv' */
1318 #define DUK_HEAP_STRING_INT_VARENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1319 #define DUK_HTHREAD_STRING_INT_VARENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1320 #define DUK_STRIDX_INT_FINALIZER 99 /* '\xffFinalizer' */
1321 #define DUK_HEAP_STRING_INT_FINALIZER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1322 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1323 #define DUK_STRIDX_INT_HANDLER 100 /* '\xffHandler' */
1324 #define DUK_HEAP_STRING_INT_HANDLER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_HANDLER)
1325 #define DUK_HTHREAD_STRING_INT_HANDLER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_HANDLER)
1326 #define DUK_STRIDX_INT_CALLEE 101 /* '\xffCallee' */
1327 #define DUK_HEAP_STRING_INT_CALLEE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_CALLEE)
1328 #define DUK_HTHREAD_STRING_INT_CALLEE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_CALLEE)
1329 #define DUK_STRIDX_INT_THREAD 102 /* '\xffThread' */
1330 #define DUK_HEAP_STRING_INT_THREAD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THREAD)
1331 #define DUK_HTHREAD_STRING_INT_THREAD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THREAD)
1332 #define DUK_STRIDX_INT_REGBASE 103 /* '\xffRegbase' */
1333 #define DUK_HEAP_STRING_INT_REGBASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_REGBASE)
1334 #define DUK_HTHREAD_STRING_INT_REGBASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_REGBASE)
1335 #define DUK_STRIDX_INT_TARGET 104 /* '\xffTarget' */
1336 #define DUK_HEAP_STRING_INT_TARGET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1337 #define DUK_HTHREAD_STRING_INT_TARGET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1338 #define DUK_STRIDX_INT_THIS 105 /* '\xffThis' */
1339 #define DUK_HEAP_STRING_INT_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_THIS)
1340 #define DUK_HTHREAD_STRING_INT_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_THIS)
1341 #define DUK_STRIDX_COMPILE 106 /* 'compile' */
1342 #define DUK_HEAP_STRING_COMPILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1343 #define DUK_HTHREAD_STRING_COMPILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1344 #define DUK_STRIDX_INPUT 107 /* 'input' */
1345 #define DUK_HEAP_STRING_INPUT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1346 #define DUK_HTHREAD_STRING_INPUT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1347 #define DUK_STRIDX_ERR_CREATE 108 /* 'errCreate' */
1348 #define DUK_HEAP_STRING_ERR_CREATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1349 #define DUK_HTHREAD_STRING_ERR_CREATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1350 #define DUK_STRIDX_ERR_THROW 109 /* 'errThrow' */
1351 #define DUK_HEAP_STRING_ERR_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1352 #define DUK_HTHREAD_STRING_ERR_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1353 #define DUK_STRIDX_ENV 110 /* 'env' */
1354 #define DUK_HEAP_STRING_ENV(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1355 #define DUK_HTHREAD_STRING_ENV(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1356 #define DUK_STRIDX_HEX 111 /* 'hex' */
1357 #define DUK_HEAP_STRING_HEX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1358 #define DUK_HTHREAD_STRING_HEX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1359 #define DUK_STRIDX_BASE64 112 /* 'base64' */
1360 #define DUK_HEAP_STRING_BASE64(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1361 #define DUK_HTHREAD_STRING_BASE64(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1362 #define DUK_STRIDX_JX 113 /* 'jx' */
1363 #define DUK_HEAP_STRING_JX(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1364 #define DUK_HTHREAD_STRING_JX(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1365 #define DUK_STRIDX_JC 114 /* 'jc' */
1366 #define DUK_HEAP_STRING_JC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1367 #define DUK_HTHREAD_STRING_JC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1368 #define DUK_STRIDX_RESUME 115 /* 'resume' */
1369 #define DUK_HEAP_STRING_RESUME(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RESUME)
1370 #define DUK_HTHREAD_STRING_RESUME(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RESUME)
1371 #define DUK_STRIDX_JSON_EXT_UNDEFINED 116 /* '{"_undef":true}' */
1372 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1373 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1374 #define DUK_STRIDX_JSON_EXT_NAN 117 /* '{"_nan":true}' */
1375 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1376 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1377 #define DUK_STRIDX_JSON_EXT_POSINF 118 /* '{"_inf":true}' */
1378 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1379 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1380 #define DUK_STRIDX_JSON_EXT_NEGINF 119 /* '{"_ninf":true}' */
1381 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1382 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1383 #define DUK_STRIDX_JSON_EXT_FUNCTION1 120 /* '{"_func":true}' */
1384 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1385 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1386 #define DUK_STRIDX_JSON_EXT_FUNCTION2 121 /* '{_func:true}' */
1387 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1388 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1389 #define DUK_STRIDX_BREAK 122 /* 'break' */
1390 #define DUK_HEAP_STRING_BREAK(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1391 #define DUK_HTHREAD_STRING_BREAK(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1392 #define DUK_STRIDX_CASE 123 /* 'case' */
1393 #define DUK_HEAP_STRING_CASE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1394 #define DUK_HTHREAD_STRING_CASE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1395 #define DUK_STRIDX_CATCH 124 /* 'catch' */
1396 #define DUK_HEAP_STRING_CATCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1397 #define DUK_HTHREAD_STRING_CATCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1398 #define DUK_STRIDX_CONTINUE 125 /* 'continue' */
1399 #define DUK_HEAP_STRING_CONTINUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1400 #define DUK_HTHREAD_STRING_CONTINUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1401 #define DUK_STRIDX_DEBUGGER 126 /* 'debugger' */
1402 #define DUK_HEAP_STRING_DEBUGGER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1403 #define DUK_HTHREAD_STRING_DEBUGGER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1404 #define DUK_STRIDX_DEFAULT 127 /* 'default' */
1405 #define DUK_HEAP_STRING_DEFAULT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1406 #define DUK_HTHREAD_STRING_DEFAULT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1407 #define DUK_STRIDX_DELETE 128 /* 'delete' */
1408 #define DUK_HEAP_STRING_DELETE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1409 #define DUK_HTHREAD_STRING_DELETE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1410 #define DUK_STRIDX_DO 129 /* 'do' */
1411 #define DUK_HEAP_STRING_DO(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1412 #define DUK_HTHREAD_STRING_DO(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1413 #define DUK_STRIDX_ELSE 130 /* 'else' */
1414 #define DUK_HEAP_STRING_ELSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1415 #define DUK_HTHREAD_STRING_ELSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1416 #define DUK_STRIDX_FINALLY 131 /* 'finally' */
1417 #define DUK_HEAP_STRING_FINALLY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1418 #define DUK_HTHREAD_STRING_FINALLY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1419 #define DUK_STRIDX_FOR 132 /* 'for' */
1420 #define DUK_HEAP_STRING_FOR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1421 #define DUK_HTHREAD_STRING_FOR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1422 #define DUK_STRIDX_LC_FUNCTION 133 /* 'function' */
1423 #define DUK_HEAP_STRING_LC_FUNCTION(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1424 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1425 #define DUK_STRIDX_IF 134 /* 'if' */
1426 #define DUK_HEAP_STRING_IF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1427 #define DUK_HTHREAD_STRING_IF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1428 #define DUK_STRIDX_IN 135 /* 'in' */
1429 #define DUK_HEAP_STRING_IN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1430 #define DUK_HTHREAD_STRING_IN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1431 #define DUK_STRIDX_INSTANCEOF 136 /* 'instanceof' */
1432 #define DUK_HEAP_STRING_INSTANCEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1433 #define DUK_HTHREAD_STRING_INSTANCEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1434 #define DUK_STRIDX_NEW 137 /* 'new' */
1435 #define DUK_HEAP_STRING_NEW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1436 #define DUK_HTHREAD_STRING_NEW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1437 #define DUK_STRIDX_RETURN 138 /* 'return' */
1438 #define DUK_HEAP_STRING_RETURN(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1439 #define DUK_HTHREAD_STRING_RETURN(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1440 #define DUK_STRIDX_SWITCH 139 /* 'switch' */
1441 #define DUK_HEAP_STRING_SWITCH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1442 #define DUK_HTHREAD_STRING_SWITCH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1443 #define DUK_STRIDX_THIS 140 /* 'this' */
1444 #define DUK_HEAP_STRING_THIS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1445 #define DUK_HTHREAD_STRING_THIS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1446 #define DUK_STRIDX_THROW 141 /* 'throw' */
1447 #define DUK_HEAP_STRING_THROW(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1448 #define DUK_HTHREAD_STRING_THROW(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1449 #define DUK_STRIDX_TRY 142 /* 'try' */
1450 #define DUK_HEAP_STRING_TRY(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1451 #define DUK_HTHREAD_STRING_TRY(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1452 #define DUK_STRIDX_TYPEOF 143 /* 'typeof' */
1453 #define DUK_HEAP_STRING_TYPEOF(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1454 #define DUK_HTHREAD_STRING_TYPEOF(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1455 #define DUK_STRIDX_VAR 144 /* 'var' */
1456 #define DUK_HEAP_STRING_VAR(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1457 #define DUK_HTHREAD_STRING_VAR(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1458 #define DUK_STRIDX_CONST 145 /* 'const' */
1459 #define DUK_HEAP_STRING_CONST(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1460 #define DUK_HTHREAD_STRING_CONST(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1461 #define DUK_STRIDX_VOID 146 /* 'void' */
1462 #define DUK_HEAP_STRING_VOID(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1463 #define DUK_HTHREAD_STRING_VOID(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1464 #define DUK_STRIDX_WHILE 147 /* 'while' */
1465 #define DUK_HEAP_STRING_WHILE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1466 #define DUK_HTHREAD_STRING_WHILE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1467 #define DUK_STRIDX_WITH 148 /* 'with' */
1468 #define DUK_HEAP_STRING_WITH(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1469 #define DUK_HTHREAD_STRING_WITH(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1470 #define DUK_STRIDX_CLASS 149 /* 'class' */
1471 #define DUK_HEAP_STRING_CLASS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1472 #define DUK_HTHREAD_STRING_CLASS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1473 #define DUK_STRIDX_ENUM 150 /* 'enum' */
1474 #define DUK_HEAP_STRING_ENUM(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1475 #define DUK_HTHREAD_STRING_ENUM(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1476 #define DUK_STRIDX_EXPORT 151 /* 'export' */
1477 #define DUK_HEAP_STRING_EXPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1478 #define DUK_HTHREAD_STRING_EXPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1479 #define DUK_STRIDX_EXTENDS 152 /* 'extends' */
1480 #define DUK_HEAP_STRING_EXTENDS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1481 #define DUK_HTHREAD_STRING_EXTENDS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1482 #define DUK_STRIDX_IMPORT 153 /* 'import' */
1483 #define DUK_HEAP_STRING_IMPORT(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1484 #define DUK_HTHREAD_STRING_IMPORT(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1485 #define DUK_STRIDX_SUPER 154 /* 'super' */
1486 #define DUK_HEAP_STRING_SUPER(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1487 #define DUK_HTHREAD_STRING_SUPER(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1488 #define DUK_STRIDX_LC_NULL 155 /* 'null' */
1489 #define DUK_HEAP_STRING_LC_NULL(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1490 #define DUK_HTHREAD_STRING_LC_NULL(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1491 #define DUK_STRIDX_TRUE 156 /* 'true' */
1492 #define DUK_HEAP_STRING_TRUE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1493 #define DUK_HTHREAD_STRING_TRUE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1494 #define DUK_STRIDX_FALSE 157 /* 'false' */
1495 #define DUK_HEAP_STRING_FALSE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1496 #define DUK_HTHREAD_STRING_FALSE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1497 #define DUK_STRIDX_IMPLEMENTS 158 /* 'implements' */
1498 #define DUK_HEAP_STRING_IMPLEMENTS(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1499 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1500 #define DUK_STRIDX_INTERFACE 159 /* 'interface' */
1501 #define DUK_HEAP_STRING_INTERFACE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1502 #define DUK_HTHREAD_STRING_INTERFACE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1503 #define DUK_STRIDX_LET 160 /* 'let' */
1504 #define DUK_HEAP_STRING_LET(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1505 #define DUK_HTHREAD_STRING_LET(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1506 #define DUK_STRIDX_PACKAGE 161 /* 'package' */
1507 #define DUK_HEAP_STRING_PACKAGE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1508 #define DUK_HTHREAD_STRING_PACKAGE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1509 #define DUK_STRIDX_PRIVATE 162 /* 'private' */
1510 #define DUK_HEAP_STRING_PRIVATE(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1511 #define DUK_HTHREAD_STRING_PRIVATE(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1512 #define DUK_STRIDX_PROTECTED 163 /* 'protected' */
1513 #define DUK_HEAP_STRING_PROTECTED(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1514 #define DUK_HTHREAD_STRING_PROTECTED(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1515 #define DUK_STRIDX_PUBLIC 164 /* 'public' */
1516 #define DUK_HEAP_STRING_PUBLIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1517 #define DUK_HTHREAD_STRING_PUBLIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1518 #define DUK_STRIDX_STATIC 165 /* 'static' */
1519 #define DUK_HEAP_STRING_STATIC(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1520 #define DUK_HTHREAD_STRING_STATIC(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1521 #define DUK_STRIDX_YIELD 166 /* 'yield' */
1522 #define DUK_HEAP_STRING_YIELD(heap) DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1523 #define DUK_HTHREAD_STRING_YIELD(thr) DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1524 
1525 #define DUK_HEAP_NUM_STRINGS 167
1526 #define DUK_STRIDX_START_RESERVED 122
1527 #define DUK_STRIDX_START_STRICT_RESERVED 158
1528 #define DUK_STRIDX_END_RESERVED 167 /* exclusive endpoint */
1529 
1530 /* To convert a heap stridx to a token number, subtract
1531  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
1532  */
1533 #if !defined(DUK_SINGLE_FILE)
1534 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[921];
1535 #endif /* !DUK_SINGLE_FILE */
1536 #define DUK_STRDATA_MAX_STRLEN 17
1537 #define DUK_STRDATA_DATA_LENGTH 921
1538 #endif /* DUK_USE_ROM_STRINGS */
1539 
1540 #if defined(DUK_USE_ROM_OBJECTS)
1541 #error RAM support not enabled, rerun configure.py with --ram-support
1542 #else /* DUK_USE_ROM_OBJECTS */
1543 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
1544 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
1545 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
1546 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
1547 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
1548 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
1549 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
1550 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
1551 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
1552 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
1553 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
1554 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
1555 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
1556 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
1557 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
1558 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
1559 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
1560 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
1561 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
1562 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
1563 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
1564 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
1565 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
1566 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
1567 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
1568 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
1569 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
1570 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
1571 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
1572 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
1573 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
1574 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
1575 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
1576 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
1577 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
1578 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
1579 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
1580 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
1581 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
1582 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
1583 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
1584 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
1585 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
1586 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
1587 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
1588 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
1589 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
1590 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
1591 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
1592 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
1593 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
1594 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
1595 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
1596 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
1597 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
1598 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
1599 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
1600 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
1601 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
1602 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
1603 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
1604 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
1605 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
1606 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
1607 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
1608 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
1609 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
1610 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
1611 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
1612 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
1613 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
1614 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
1615 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
1616 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
1617 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
1618 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
1619 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
1620 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
1621 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
1622 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
1623 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
1624 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
1625 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
1626 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
1627 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
1628 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
1629 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
1630 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
1631 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
1632 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
1633 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
1634 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
1635 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
1636 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
1637 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
1638 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
1639 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
1640 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
1641 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
1642 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
1643 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
1644 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
1645 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
1646 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
1647 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
1648 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
1649 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
1650 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
1651 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
1652 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
1653 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
1654 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
1655 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
1656 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
1657 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
1658 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
1659 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
1660 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
1661 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
1662 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
1663 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
1664 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
1665 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
1666 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
1667 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
1668 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
1669 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
1670 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
1671 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
1672 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
1673 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
1674 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
1675 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
1676 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
1677 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
1678 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
1679 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
1680 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
1681 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
1682 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
1683 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
1684 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
1685 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
1686 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
1687 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
1688 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
1689 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
1690 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
1691 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
1692 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
1693 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
1694 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
1695 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
1696 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
1697 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
1698 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
1699 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
1700 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
1701 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
1702 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
1703 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
1704 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
1705 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
1706 #if !defined(DUK_SINGLE_FILE)
1707 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[164];
1708 #endif /* !DUK_SINGLE_FILE */
1709 #define DUK_BIDX_GLOBAL 0
1710 #define DUK_BIDX_GLOBAL_ENV 1
1711 #define DUK_BIDX_OBJECT_CONSTRUCTOR 2
1712 #define DUK_BIDX_OBJECT_PROTOTYPE 3
1713 #define DUK_BIDX_FUNCTION_CONSTRUCTOR 4
1714 #define DUK_BIDX_FUNCTION_PROTOTYPE 5
1715 #define DUK_BIDX_ARRAY_CONSTRUCTOR 6
1716 #define DUK_BIDX_ARRAY_PROTOTYPE 7
1717 #define DUK_BIDX_STRING_CONSTRUCTOR 8
1718 #define DUK_BIDX_STRING_PROTOTYPE 9
1719 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR 10
1720 #define DUK_BIDX_BOOLEAN_PROTOTYPE 11
1721 #define DUK_BIDX_NUMBER_CONSTRUCTOR 12
1722 #define DUK_BIDX_NUMBER_PROTOTYPE 13
1723 #define DUK_BIDX_DATE_CONSTRUCTOR 14
1724 #define DUK_BIDX_DATE_PROTOTYPE 15
1725 #define DUK_BIDX_REGEXP_CONSTRUCTOR 16
1726 #define DUK_BIDX_REGEXP_PROTOTYPE 17
1727 #define DUK_BIDX_ERROR_CONSTRUCTOR 18
1728 #define DUK_BIDX_ERROR_PROTOTYPE 19
1729 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR 20
1730 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE 21
1731 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR 22
1732 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE 23
1733 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR 24
1734 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE 25
1735 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR 26
1736 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE 27
1737 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR 28
1738 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE 29
1739 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR 30
1740 #define DUK_BIDX_URI_ERROR_PROTOTYPE 31
1741 #define DUK_BIDX_MATH 32
1742 #define DUK_BIDX_JSON 33
1743 #define DUK_BIDX_TYPE_ERROR_THROWER 34
1744 #define DUK_BIDX_DUKTAPE 35
1745 #define DUK_BIDX_THREAD_CONSTRUCTOR 36
1746 #define DUK_BIDX_THREAD_PROTOTYPE 37
1747 #define DUK_BIDX_POINTER_CONSTRUCTOR 38
1748 #define DUK_BIDX_POINTER_PROTOTYPE 39
1749 #define DUK_BIDX_DOUBLE_ERROR 40
1750 #define DUK_BIDX_PROXY_CONSTRUCTOR 41
1751 #define DUK_BIDX_REFLECT 42
1752 #define DUK_BIDX_SYMBOL_PROTOTYPE 43
1753 #define DUK_BIDX_ARRAYBUFFER_CONSTRUCTOR 44
1754 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE 45
1755 #define DUK_BIDX_DATAVIEW_CONSTRUCTOR 46
1756 #define DUK_BIDX_DATAVIEW_PROTOTYPE 47
1757 #define DUK_BIDX_TYPEDARRAY_CONSTRUCTOR 48
1758 #define DUK_BIDX_TYPEDARRAY_PROTOTYPE 49
1759 #define DUK_BIDX_INT8ARRAY_CONSTRUCTOR 50
1760 #define DUK_BIDX_INT8ARRAY_PROTOTYPE 51
1761 #define DUK_BIDX_UINT8ARRAY_CONSTRUCTOR 52
1762 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE 53
1763 #define DUK_BIDX_UINT8CLAMPEDARRAY_CONSTRUCTOR 54
1764 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE 55
1765 #define DUK_BIDX_INT16ARRAY_CONSTRUCTOR 56
1766 #define DUK_BIDX_INT16ARRAY_PROTOTYPE 57
1767 #define DUK_BIDX_UINT16ARRAY_CONSTRUCTOR 58
1768 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE 59
1769 #define DUK_BIDX_INT32ARRAY_CONSTRUCTOR 60
1770 #define DUK_BIDX_INT32ARRAY_PROTOTYPE 61
1771 #define DUK_BIDX_UINT32ARRAY_CONSTRUCTOR 62
1772 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE 63
1773 #define DUK_BIDX_FLOAT32ARRAY_CONSTRUCTOR 64
1774 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE 65
1775 #define DUK_BIDX_FLOAT64ARRAY_CONSTRUCTOR 66
1776 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE 67
1777 #define DUK_BIDX_NODEJS_BUFFER_CONSTRUCTOR 68
1778 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE 69
1779 #define DUK_BIDX_TEXTENCODER_CONSTRUCTOR 70
1780 #define DUK_BIDX_TEXTENCODER_PROTOTYPE 71
1781 #define DUK_BIDX_TEXTDECODER_CONSTRUCTOR 72
1782 #define DUK_BIDX_TEXTDECODER_PROTOTYPE 73
1783 #define DUK_NUM_BUILTINS 74
1784 #define DUK_NUM_BIDX_BUILTINS 74
1785 #define DUK_NUM_ALL_BUILTINS 74
1786 #if defined(DUK_USE_DOUBLE_LE)
1787 #if !defined(DUK_SINGLE_FILE)
1788 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3790];
1789 #endif /* !DUK_SINGLE_FILE */
1790 #define DUK_BUILTINS_DATA_LENGTH 3790
1791 #elif defined(DUK_USE_DOUBLE_BE)
1792 #if !defined(DUK_SINGLE_FILE)
1793 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3790];
1794 #endif /* !DUK_SINGLE_FILE */
1795 #define DUK_BUILTINS_DATA_LENGTH 3790
1796 #elif defined(DUK_USE_DOUBLE_ME)
1797 #if !defined(DUK_SINGLE_FILE)
1798 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3790];
1799 #endif /* !DUK_SINGLE_FILE */
1800 #define DUK_BUILTINS_DATA_LENGTH 3790
1801 #else
1802 #error invalid endianness defines
1803 #endif
1804 #endif /* DUK_USE_ROM_OBJECTS */
1805 #endif /* DUK_BUILTINS_H_INCLUDED */
1806 
1807 /* #include duk_util.h */
1808 /*
1809  * Utilities
1810  */
1811 
1812 #if !defined(DUK_UTIL_H_INCLUDED)
1813 #define DUK_UTIL_H_INCLUDED
1814 
1815 #define DUK_UTIL_MIN_HASH_PRIME 17 /* must match genhashsizes.py */
1816 
1817 #define DUK_UTIL_GET_HASH_PROBE_STEP(hash) (duk_util_probe_steps[(hash) & 0x1f])
1818 
1819 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
1820 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
1821 #else
1822 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
1823 #endif
1824 
1825 /*
1826  * Some useful constants
1827  */
1828 
1829 #define DUK_DOUBLE_2TO32 4294967296.0
1830 #define DUK_DOUBLE_2TO31 2147483648.0
1831 #define DUK_DOUBLE_LOG2E 1.4426950408889634
1832 #define DUK_DOUBLE_LOG10E 0.4342944819032518
1833 
1834 /*
1835  * Endian conversion
1836  */
1837 
1838 #if defined(DUK_USE_INTEGER_LE)
1839 #define DUK_HTON32(x) DUK_BSWAP32((x))
1840 #define DUK_NTOH32(x) DUK_BSWAP32((x))
1841 #define DUK_HTON16(x) DUK_BSWAP16((x))
1842 #define DUK_NTOH16(x) DUK_BSWAP16((x))
1843 #elif defined(DUK_USE_INTEGER_BE)
1844 #define DUK_HTON32(x) (x)
1845 #define DUK_NTOH32(x) (x)
1846 #define DUK_HTON16(x) (x)
1847 #define DUK_NTOH16(x) (x)
1848 #else
1849 #error internal error, endianness defines broken
1850 #endif
1851 
1852 /*
1853  * Bitstream decoder
1854  */
1855 
1857  const duk_uint8_t *data;
1858  duk_size_t offset;
1859  duk_size_t length;
1860  duk_uint32_t currval;
1861  duk_small_int_t currbits;
1862 };
1863 
1864 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
1865 
1866 /*
1867  * Bitstream encoder
1868  */
1869 
1871  duk_uint8_t *data;
1872  duk_size_t offset;
1873  duk_size_t length;
1874  duk_uint32_t currval;
1875  duk_small_int_t currbits;
1876  duk_small_int_t truncated;
1877 };
1878 
1879 /*
1880  * Raw write/read macros for big endian, unaligned basic values.
1881  * Caller ensures there's enough space. The macros update the pointer
1882  * argument automatically on resizes. The idiom seems a bit odd, but
1883  * leads to compact code.
1884  */
1885 
1886 #define DUK_RAW_WRITE_U8(ptr,val) do { \
1887  *(ptr)++ = (duk_uint8_t) (val); \
1888  } while (0)
1889 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
1890 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
1891 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
1892 #define DUK_RAW_WRITE_XUTF8(ptr,val) do { \
1893  /* 'ptr' is evaluated both as LHS and RHS. */ \
1894  duk_uint8_t *duk__ptr; \
1895  duk_small_int_t duk__len; \
1896  duk__ptr = (duk_uint8_t *) (ptr); \
1897  duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
1898  duk__ptr += duk__len; \
1899  (ptr) = duk__ptr; \
1900  } while (0)
1901 #define DUK_RAW_WRITE_CESU8(ptr,val) do { \
1902  /* 'ptr' is evaluated both as LHS and RHS. */ \
1903  duk_uint8_t *duk__ptr; \
1904  duk_small_int_t duk__len; \
1905  duk__ptr = (duk_uint8_t *) (ptr); \
1906  duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
1907  duk__ptr += duk__len; \
1908  (ptr) = duk__ptr; \
1909  } while (0)
1910 
1911 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
1912 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
1913 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
1914 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
1915 
1916 /*
1917  * Buffer writer (dynamic buffer only)
1918  *
1919  * Helper for writing to a dynamic buffer with a concept of a "spare" area
1920  * to reduce resizes. You can ensure there is enough space beforehand and
1921  * then write for a while without further checks, relying on a stable data
1922  * pointer. Spare handling is automatic so call sites only indicate how
1923  * much data they need right now.
1924  *
1925  * There are several ways to write using bufwriter. The best approach
1926  * depends mainly on how much performance matters over code footprint.
1927  * The key issues are (1) ensuring there is space and (2) keeping the
1928  * pointers consistent. Fast code should ensure space for multiple writes
1929  * with one ensure call. Fastest inner loop code can temporarily borrow
1930  * the 'p' pointer but must write it back eventually.
1931  *
1932  * Be careful to ensure all macro arguments (other than static pointers like
1933  * 'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
1934  * necessary (if that's not possible, there should be a note near the macro).
1935  * Buffer write arguments often contain arithmetic etc so this is
1936  * particularly important here.
1937  */
1938 
1939 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
1940 
1942  duk_uint8_t *p;
1943  duk_uint8_t *p_base;
1944  duk_uint8_t *p_limit;
1945  duk_hbuffer_dynamic *buf;
1946 };
1947 
1948 #define DUK_BW_SPARE_ADD 64
1949 #define DUK_BW_SPARE_SHIFT 4 /* 2^4 -> 1/16 = 6.25% spare */
1950 
1951 /* Initialization and finalization (compaction), converting to other types. */
1952 
1953 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
1954  duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
1955  } while (0)
1956 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
1957  duk_bw_init((thr), (bw_ctx), (buf)); \
1958  } while (0)
1959 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
1960  /* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
1961  duk_bw_compact((thr), (bw_ctx)); \
1962  } while (0)
1963 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
1964  duk_push_lstring((duk_context *) (thr), \
1965  (const char *) (bw_ctx)->p_base, \
1966  (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
1967  } while (0)
1968 /* Pointers may be NULL for a while when 'buf' size is zero and before any
1969  * ENSURE calls have been made. Once an ENSURE has been made, the pointers
1970  * are required to be non-NULL so that it's always valid to use memcpy() and
1971  * memmove(), even for zero size.
1972  */
1973 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
1974  DUK_ASSERT_EXPR((bw_ctx) != NULL && \
1975  (bw_ctx)->buf != NULL && \
1976  ((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
1977  ((bw_ctx)->p != NULL && \
1978  (bw_ctx)->p_base != NULL && \
1979  (bw_ctx)->p_limit != NULL && \
1980  (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
1981  (bw_ctx)->p >= (bw_ctx)->p_base && \
1982  (bw_ctx)->p <= (bw_ctx)->p_limit)))
1983 #define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
1984  DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
1985  } while (0)
1986 
1987 /* Working with the pointer and current size. */
1988 
1989 #define DUK_BW_GET_PTR(thr,bw_ctx) \
1990  ((bw_ctx)->p)
1991 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
1992  (bw_ctx)->p = (ptr); \
1993  } while (0)
1994 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
1995  (bw_ctx)->p += (delta); \
1996  } while (0)
1997 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
1998  ((bw_ctx)->p_base)
1999 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2000  ((bw_ctx)->p_limit)
2001 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2002  ((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2003 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2004  DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2005  (bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2006  } while (0)
2007 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2008  /* Reset to zero size, keep current limit. */ \
2009  (bw_ctx)->p = (bw_ctx)->p_base; \
2010  } while (0)
2011 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2012  ((bw_ctx)->buf)
2013 
2014 /* Ensuring (reserving) space. */
2015 
2016 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2017  duk_size_t duk__sz, duk__space; \
2018  DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2019  duk__sz = (sz); \
2020  duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2021  if (duk__space < duk__sz) { \
2022  (void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2023  } \
2024  } while (0)
2025 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2026 /* XXX: Rework to use an always-inline function? */
2027 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2028  (((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2029  (ptr) : \
2030  ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2031 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2032  DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2033 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2034  (DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2035  DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2036 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2037  DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2038  } while (0)
2039 
2040 /* Miscellaneous. */
2041 
2042 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2043  (bw_ctx)->p = (ptr); \
2044  duk_bw_compact((thr), (bw_ctx)); \
2045  } while (0)
2046 
2047 /* Fast write calls which assume you control the spare beforehand.
2048  * Multibyte write variants exist and use a temporary write pointer
2049  * because byte writes alias with anything: with a stored pointer
2050  * explicit pointer load/stores get generated (e.g. gcc -Os).
2051  */
2052 
2053 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2054  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2055  *(bw_ctx)->p++ = (duk_uint8_t) (val); \
2056  } while (0)
2057 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2058  duk_uint8_t *duk__p; \
2059  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2060  duk__p = (bw_ctx)->p; \
2061  *duk__p++ = (duk_uint8_t) (val1); \
2062  *duk__p++ = (duk_uint8_t) (val2); \
2063  (bw_ctx)->p = duk__p; \
2064  } while (0)
2065 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2066  duk_uint8_t *duk__p; \
2067  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2068  duk__p = (bw_ctx)->p; \
2069  *duk__p++ = (duk_uint8_t) (val1); \
2070  *duk__p++ = (duk_uint8_t) (val2); \
2071  *duk__p++ = (duk_uint8_t) (val3); \
2072  (bw_ctx)->p = duk__p; \
2073  } while (0)
2074 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2075  duk_uint8_t *duk__p; \
2076  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2077  duk__p = (bw_ctx)->p; \
2078  *duk__p++ = (duk_uint8_t) (val1); \
2079  *duk__p++ = (duk_uint8_t) (val2); \
2080  *duk__p++ = (duk_uint8_t) (val3); \
2081  *duk__p++ = (duk_uint8_t) (val4); \
2082  (bw_ctx)->p = duk__p; \
2083  } while (0)
2084 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2085  duk_uint8_t *duk__p; \
2086  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2087  duk__p = (bw_ctx)->p; \
2088  *duk__p++ = (duk_uint8_t) (val1); \
2089  *duk__p++ = (duk_uint8_t) (val2); \
2090  *duk__p++ = (duk_uint8_t) (val3); \
2091  *duk__p++ = (duk_uint8_t) (val4); \
2092  *duk__p++ = (duk_uint8_t) (val5); \
2093  (bw_ctx)->p = duk__p; \
2094  } while (0)
2095 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2096  duk_uint8_t *duk__p; \
2097  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2098  duk__p = (bw_ctx)->p; \
2099  *duk__p++ = (duk_uint8_t) (val1); \
2100  *duk__p++ = (duk_uint8_t) (val2); \
2101  *duk__p++ = (duk_uint8_t) (val3); \
2102  *duk__p++ = (duk_uint8_t) (val4); \
2103  *duk__p++ = (duk_uint8_t) (val5); \
2104  *duk__p++ = (duk_uint8_t) (val6); \
2105  (bw_ctx)->p = duk__p; \
2106  } while (0)
2107 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2108  duk_ucodepoint_t duk__cp; \
2109  duk_small_int_t duk__enc_len; \
2110  duk__cp = (cp); \
2111  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2112  duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2113  (bw_ctx)->p += duk__enc_len; \
2114  } while (0)
2115 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2116  duk_ucodepoint_t duk__cp; \
2117  duk_small_int_t duk__enc_len; \
2118  duk__cp = (duk_ucodepoint_t) (cp); \
2119  DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2120  duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2121  (bw_ctx)->p += duk__enc_len; \
2122  } while (0)
2123 /* XXX: add temporary duk__p pointer here too; sharing */
2124 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2125  const void *duk__valptr; \
2126  duk_size_t duk__valsz; \
2127  duk__valptr = (const void *) (valptr); \
2128  duk__valsz = (duk_size_t) (valsz); \
2129  DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2130  (bw_ctx)->p += duk__valsz; \
2131  } while (0)
2132 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2133  const duk_uint8_t *duk__val; \
2134  duk_size_t duk__val_len; \
2135  duk__val = (const duk_uint8_t *) (val); \
2136  duk__val_len = DUK_STRLEN((const char *) duk__val); \
2137  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2138  (bw_ctx)->p += duk__val_len; \
2139  } while (0)
2140 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2141  duk_size_t duk__val_len; \
2142  duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2143  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2144  (bw_ctx)->p += duk__val_len; \
2145  } while (0)
2146 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2147  duk_size_t duk__val_len; \
2148  duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2149  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2150  (bw_ctx)->p += duk__val_len; \
2151  } while (0)
2152 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2153  duk_size_t duk__val_len; \
2154  duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2155  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2156  (bw_ctx)->p += duk__val_len; \
2157  } while (0)
2158 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2159  duk_size_t duk__val_len; \
2160  duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2161  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2162  (bw_ctx)->p += duk__val_len; \
2163  } while (0)
2164 
2165 /* Append bytes from a slice already in the buffer. */
2166 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2167  duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2168 
2169 /* Insert bytes in the middle of the buffer from an external buffer. */
2170 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2171  duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2172 
2173 /* Insert bytes in the middle of the buffer from a slice already
2174  * in the buffer. Source offset is interpreted "before" the operation.
2175  */
2176 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2177  duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2178 
2179 /* Insert a reserved area somewhere in the buffer; caller fills it.
2180  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2181  * area for convenience.
2182  */
2183 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2184  duk_bw_insert_raw_area((thr), (bw), (off), (len))
2185 
2186 /* Remove a slice from inside buffer. */
2187 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2188  duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2189 
2190 /* Safe write calls which will ensure space first. */
2191 
2192 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2193  DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2194  DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2195  } while (0)
2196 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2197  DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2198  DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2199  } while (0)
2200 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2201  DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2202  DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2203  } while (0)
2204 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2205  DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2206  DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2207  } while (0)
2208 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2209  DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2210  DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2211  } while (0)
2212 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2213  DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2214  DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2215  } while (0)
2216 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2217  DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2218  DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2219  } while (0)
2220 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2221  DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2222  DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2223  } while (0)
2224 /* XXX: add temporary duk__p pointer here too; sharing */
2225 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2226  const void *duk__valptr; \
2227  duk_size_t duk__valsz; \
2228  duk__valptr = (const void *) (valptr); \
2229  duk__valsz = (duk_size_t) (valsz); \
2230  DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2231  DUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2232  (bw_ctx)->p += duk__valsz; \
2233  } while (0)
2234 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2235  const duk_uint8_t *duk__val; \
2236  duk_size_t duk__val_len; \
2237  duk__val = (const duk_uint8_t *) (val); \
2238  duk__val_len = DUK_STRLEN((const char *) duk__val); \
2239  DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2240  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2241  (bw_ctx)->p += duk__val_len; \
2242  } while (0)
2243 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2244  duk_size_t duk__val_len; \
2245  duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2246  DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2247  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2248  (bw_ctx)->p += duk__val_len; \
2249  } while (0)
2250 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2251  duk_size_t duk__val_len; \
2252  duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2253  DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2254  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2255  (bw_ctx)->p += duk__val_len; \
2256  } while (0)
2257 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2258  duk_size_t duk__val_len; \
2259  duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2260  DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2261  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2262  (bw_ctx)->p += duk__val_len; \
2263  } while (0)
2264 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2265  duk_size_t duk__val_len; \
2266  duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2267  DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2268  DUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2269  (bw_ctx)->p += duk__val_len; \
2270  } while (0)
2271 
2272 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2273  duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2274 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2275  duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2276 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2277  duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2278 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2279  /* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2280  duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2281 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2282  /* No difference between raw/ensure because the buffer shrinks. */ \
2283  DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2284 
2285 /*
2286  * Externs and prototypes
2287  */
2288 
2289 #if !defined(DUK_SINGLE_FILE)
2290 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2291 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2292 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2293 #if defined(DUK_USE_HEX_FASTPATH)
2294 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2295 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2296 #endif
2297 #if defined(DUK_USE_BASE64_FASTPATH)
2298 DUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];
2299 DUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];
2300 #endif
2301 #endif /* !DUK_SINGLE_FILE */
2302 
2303 /* Note: assumes that duk_util_probe_steps size is 32 */
2304 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2305 #if !defined(DUK_SINGLE_FILE)
2306 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2307 #endif /* !DUK_SINGLE_FILE */
2308 #endif
2309 
2310 #if defined(DUK_USE_STRHASH_DENSE)
2311 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2312 #endif
2313 
2314 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
2315 DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size);
2316 #endif
2317 
2318 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2319 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2320 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2321 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2322 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2323 
2324 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2325 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2326 
2327 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2328 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2329 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2330 #endif
2331 
2332 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2333 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2334 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2335 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2336 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);
2337 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);
2338 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);
2339 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);
2340 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);
2341 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);
2342 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);
2343 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);
2344 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2345 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2346 
2347 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2348 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2349 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
2350 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2351 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2352 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2353 
2354 #if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
2355 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2356 #endif
2357 
2358 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
2359 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
2360 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
2361 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
2362 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
2363 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
2364 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
2365 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
2366 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
2367 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
2368 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
2369 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
2370 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
2371 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
2372 
2373 #endif /* DUK_UTIL_H_INCLUDED */
2374 /* #include duk_strings.h */
2375 /*
2376  * Shared string macros.
2377  *
2378  * Using shared macros helps minimize strings data size because it's easy
2379  * to check if an existing string could be used. String constants don't
2380  * need to be all defined here; defining a string here makes sense if there's
2381  * a high chance the string could be reused. Also, using macros allows
2382  * a call site express the exact string needed, but the macro may map to an
2383  * approximate string to reduce unique string count. Macros can also be
2384  * more easily tuned for low memory targets than #if defined()s throughout
2385  * the code base.
2386  *
2387  * Because format strings behave differently in the call site (they need to
2388  * be followed by format arguments), they use a special prefix DUK_STR_FMT_.
2389  *
2390  * On some compilers using explicit shared strings is preferable; on others
2391  * it may be better to use straight literals because the compiler will combine
2392  * them anyway, and such strings won't end up unnecessarily in a symbol table.
2393  */
2394 
2395 #if !defined(DUK_ERRMSG_H_INCLUDED)
2396 #define DUK_ERRMSG_H_INCLUDED
2397 
2398 /* Mostly API and built-in method related */
2399 #define DUK_STR_INTERNAL_ERROR "internal error"
2400 #define DUK_STR_UNSUPPORTED "unsupported"
2401 #define DUK_STR_INVALID_COUNT "invalid count"
2402 #define DUK_STR_INVALID_ARGS "invalid args"
2403 #define DUK_STR_INVALID_STATE "invalid state"
2404 #define DUK_STR_INVALID_INPUT "invalid input"
2405 #define DUK_STR_INVALID_LENGTH "invalid length"
2406 #define DUK_STR_NOT_CONSTRUCTABLE "not constructable"
2407 #define DUK_STR_CONSTRUCT_ONLY "constructor requires 'new'"
2408 #define DUK_STR_NOT_CALLABLE "not callable"
2409 #define DUK_STR_NOT_EXTENSIBLE "not extensible"
2410 #define DUK_STR_NOT_WRITABLE "not writable"
2411 #define DUK_STR_NOT_CONFIGURABLE "not configurable"
2412 #define DUK_STR_INVALID_CONTEXT "invalid context"
2413 #define DUK_STR_INVALID_INDEX "invalid args"
2414 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK "cannot push beyond allocated stack"
2415 #define DUK_STR_NOT_UNDEFINED "unexpected type"
2416 #define DUK_STR_NOT_NULL "unexpected type"
2417 #define DUK_STR_NOT_BOOLEAN "unexpected type"
2418 #define DUK_STR_NOT_NUMBER "unexpected type"
2419 #define DUK_STR_NOT_STRING "unexpected type"
2420 #define DUK_STR_NOT_OBJECT "unexpected type"
2421 #define DUK_STR_NOT_POINTER "unexpected type"
2422 #define DUK_STR_NOT_BUFFER "not buffer" /* still in use with verbose messages */
2423 #define DUK_STR_UNEXPECTED_TYPE "unexpected type"
2424 #define DUK_STR_NOT_THREAD "unexpected type"
2425 #define DUK_STR_NOT_COMPFUNC "unexpected type"
2426 #define DUK_STR_NOT_NATFUNC "unexpected type"
2427 #define DUK_STR_NOT_C_FUNCTION "unexpected type"
2428 #define DUK_STR_NOT_FUNCTION "unexpected type"
2429 #define DUK_STR_NOT_REGEXP "unexpected type"
2430 #define DUK_STR_TOPRIMITIVE_FAILED "coercion to primitive failed"
2431 #define DUK_STR_NUMBER_OUTSIDE_RANGE "number outside range"
2432 #define DUK_STR_NOT_OBJECT_COERCIBLE "not object coercible"
2433 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL "cannot number coerce Symbol"
2434 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL "cannot string coerce Symbol"
2435 #define DUK_STR_STRING_TOO_LONG "string too long"
2436 #define DUK_STR_BUFFER_TOO_LONG "buffer too long"
2437 #define DUK_STR_ALLOC_FAILED "alloc failed"
2438 #define DUK_STR_WRONG_BUFFER_TYPE "wrong buffer type"
2439 #define DUK_STR_ENCODE_FAILED "encode failed"
2440 #define DUK_STR_DECODE_FAILED "decode failed"
2441 #define DUK_STR_NO_SOURCECODE "no sourcecode"
2442 #define DUK_STR_RESULT_TOO_LONG "result too long"
2443 
2444 /* JSON */
2445 #define DUK_STR_FMT_PTR "%p"
2446 #define DUK_STR_FMT_INVALID_JSON "invalid json (at offset %ld)"
2447 #define DUK_STR_JSONDEC_RECLIMIT "json decode recursion limit"
2448 #define DUK_STR_JSONENC_RECLIMIT "json encode recursion limit"
2449 #define DUK_STR_CYCLIC_INPUT "cyclic input"
2450 
2451 /* Object property access */
2452 #define DUK_STR_PROXY_REVOKED "proxy revoked"
2453 #define DUK_STR_INVALID_BASE "invalid base value"
2454 #define DUK_STR_STRICT_CALLER_READ "cannot read strict 'caller'"
2455 #define DUK_STR_PROXY_REJECTED "proxy rejected"
2456 #define DUK_STR_INVALID_ARRAY_LENGTH "invalid array length"
2457 #define DUK_STR_SETTER_UNDEFINED "setter undefined"
2458 #define DUK_STR_INVALID_DESCRIPTOR "invalid descriptor"
2459 
2460 /* Proxy */
2461 #define DUK_STR_INVALID_TRAP_RESULT "invalid trap result"
2462 
2463 /* Variables */
2464 
2465 /* Lexer */
2466 #define DUK_STR_INVALID_ESCAPE "invalid escape"
2467 #define DUK_STR_UNTERMINATED_STRING "unterminated string"
2468 #define DUK_STR_UNTERMINATED_COMMENT "unterminated comment"
2469 #define DUK_STR_UNTERMINATED_REGEXP "unterminated regexp"
2470 #define DUK_STR_TOKEN_LIMIT "token limit"
2471 #define DUK_STR_REGEXP_SUPPORT_DISABLED "regexp support disabled"
2472 #define DUK_STR_INVALID_NUMBER_LITERAL "invalid number literal"
2473 #define DUK_STR_INVALID_TOKEN "invalid token"
2474 
2475 /* Compiler */
2476 #define DUK_STR_PARSE_ERROR "parse error"
2477 #define DUK_STR_DUPLICATE_LABEL "duplicate label"
2478 #define DUK_STR_INVALID_LABEL "invalid label"
2479 #define DUK_STR_INVALID_ARRAY_LITERAL "invalid array literal"
2480 #define DUK_STR_INVALID_OBJECT_LITERAL "invalid object literal"
2481 #define DUK_STR_INVALID_VAR_DECLARATION "invalid variable declaration"
2482 #define DUK_STR_CANNOT_DELETE_IDENTIFIER "cannot delete identifier"
2483 #define DUK_STR_INVALID_EXPRESSION "invalid expression"
2484 #define DUK_STR_INVALID_LVALUE "invalid lvalue"
2485 #define DUK_STR_EXPECTED_IDENTIFIER "expected identifier"
2486 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED "empty expression not allowed"
2487 #define DUK_STR_INVALID_FOR "invalid for statement"
2488 #define DUK_STR_INVALID_SWITCH "invalid switch statement"
2489 #define DUK_STR_INVALID_BREAK_CONT_LABEL "invalid break/continue label"
2490 #define DUK_STR_INVALID_RETURN "invalid return"
2491 #define DUK_STR_INVALID_TRY "invalid try"
2492 #define DUK_STR_INVALID_THROW "invalid throw"
2493 #define DUK_STR_WITH_IN_STRICT_MODE "with in strict mode"
2494 #define DUK_STR_FUNC_STMT_NOT_ALLOWED "function statement not allowed"
2495 #define DUK_STR_UNTERMINATED_STMT "unterminated statement"
2496 #define DUK_STR_INVALID_ARG_NAME "invalid argument name"
2497 #define DUK_STR_INVALID_FUNC_NAME "invalid function name"
2498 #define DUK_STR_INVALID_GETSET_NAME "invalid getter/setter name"
2499 #define DUK_STR_FUNC_NAME_REQUIRED "function name required"
2500 
2501 /* Regexp */
2502 #define DUK_STR_INVALID_QUANTIFIER "invalid regexp quantifier"
2503 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM "quantifier without preceding atom"
2504 #define DUK_STR_INVALID_QUANTIFIER_VALUES "quantifier values invalid (qmin > qmax)"
2505 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES "quantifier requires too many atom copies"
2506 #define DUK_STR_UNEXPECTED_CLOSING_PAREN "unexpected closing parenthesis"
2507 #define DUK_STR_UNEXPECTED_END_OF_PATTERN "unexpected end of pattern"
2508 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN "unexpected token in regexp"
2509 #define DUK_STR_INVALID_REGEXP_FLAGS "invalid regexp flags"
2510 #define DUK_STR_INVALID_REGEXP_ESCAPE "invalid regexp escape"
2511 #define DUK_STR_INVALID_BACKREFS "invalid backreference(s)"
2512 #define DUK_STR_INVALID_REGEXP_CHARACTER "invalid regexp character"
2513 #define DUK_STR_UNTERMINATED_CHARCLASS "unterminated character class"
2514 #define DUK_STR_INVALID_RANGE "invalid range"
2515 
2516 /* Limits */
2517 #define DUK_STR_VALSTACK_LIMIT "valstack limit"
2518 #define DUK_STR_CALLSTACK_LIMIT "callstack limit"
2519 #define DUK_STR_CATCHSTACK_LIMIT "catchstack limit"
2520 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT "prototype chain limit"
2521 #define DUK_STR_BOUND_CHAIN_LIMIT "function call bound chain limit"
2522 #define DUK_STR_C_CALLSTACK_LIMIT "C call stack depth limit"
2523 #define DUK_STR_COMPILER_RECURSION_LIMIT "compiler recursion limit"
2524 #define DUK_STR_BYTECODE_LIMIT "bytecode limit"
2525 #define DUK_STR_REG_LIMIT "register limit"
2526 #define DUK_STR_TEMP_LIMIT "temp limit"
2527 #define DUK_STR_CONST_LIMIT "const limit"
2528 #define DUK_STR_FUNC_LIMIT "function limit"
2529 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT "regexp compiler recursion limit"
2530 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT "regexp executor recursion limit"
2531 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT "regexp step limit"
2532 
2533 #endif /* DUK_ERRMSG_H_INCLUDED */
2534 /* #include duk_js_bytecode.h */
2535 /*
2536  * Ecmascript bytecode
2537  */
2538 
2539 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
2540 #define DUK_JS_BYTECODE_H_INCLUDED
2541 
2542 /*
2543  * Bytecode instruction layout
2544  * ===========================
2545  *
2546  * Instructions are unsigned 32-bit integers divided as follows:
2547  *
2548  * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2549  * !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!
2550  * +-----------------------------------------------+---------------+
2551  * ! C ! B ! A ! OP !
2552  * +-----------------------------------------------+---------------+
2553  *
2554  * OP (8 bits): opcode (DUK_OP_*), access should be fastest
2555  * consecutive opcodes allocated when opcode needs flags
2556  * A (8 bits): typically a target register number
2557  * B (8 bits): typically first source register/constant number
2558  * C (8 bits): typically second source register/constant number
2559  *
2560  * Some instructions combine BC or ABC together for larger parameter values.
2561  * Signed integers (e.g. jump offsets) are encoded as unsigned, with an
2562  * opcode specific bias.
2563  *
2564  * Some opcodes have flags which are handled by allocating consecutive
2565  * opcodes to make space for 1-N flags. Flags can also be e.g. in the 'A'
2566  * field when there's room for the specific opcode.
2567  *
2568  * For example, if three flags were needed, they could be allocated from
2569  * the opcode field as follows:
2570  *
2571  * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2572  * !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!
2573  * +-----------------------------------------------+---------------+
2574  * ! C ! B ! A ! OP !Z!Y!X!
2575  * +-----------------------------------------------+---------------+
2576  *
2577  * Some opcodes accept a reg/const argument which is handled by allocating
2578  * flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST(). The
2579  * following convention is shared by most opcodes, so that the compiler
2580  * can handle reg/const flagging without opcode specific code paths:
2581  *
2582  * !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
2583  * !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!
2584  * +-----------------------------------------------+---------------+
2585  * ! C ! B ! A ! OP !Y!X!
2586  * +-----------------------------------------------+---------------+
2587  *
2588  * X 1=B is const, 0=B is reg
2589  * Y 1=C is const, 0=C is reg
2590  *
2591  * In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
2592  * 8-bit opcode space for a single logical opcode. The base opcode
2593  * number should be divisible by 4. If the opcode is called 'FOO'
2594  * the following opcode constants would be defined:
2595  *
2596  * DUK_OP_FOO 100 // base opcode number
2597  * DUK_OP_FOO_RR 100 // FOO, B=reg, C=reg
2598  * DUK_OP_FOO_CR 101 // FOO, B=const, C=reg
2599  * DUK_OP_FOO_RC 102 // FOO, B=reg, C=const
2600  * DUK_OP_FOO_CC 103 // FOO, B=const, C=const
2601  *
2602  * If only B or C is a reg/const, the unused opcode combinations can be
2603  * used for other opcodes (which take no reg/const argument). However,
2604  * such opcode values are initially reserved, at least while opcode space
2605  * is available. For example, if 'BAR' uses B for a register field and
2606  * C is a reg/const:
2607  *
2608  * DUK_OP_BAR 116 // base opcode number
2609  * DUK_OP_BAR_RR 116 // BAR, B=reg, C=reg
2610  * DUK_OP_BAR_CR_UNUSED 117 // unused, could be repurposed
2611  * DUK_OP_BAR_RC 118 // BAR, B=reg, C=const
2612  * DUK_OP_BAR_CC_UNUSED 119 // unused, could be repurposed
2613  *
2614  * Macro naming is a bit misleading, e.g. "ABC" in macro name but the
2615  * field layout is concretely "CBA" in the register.
2616  */
2617 
2618 typedef duk_uint32_t duk_instr_t;
2619 
2620 #define DUK_BC_SHIFT_OP 0
2621 #define DUK_BC_SHIFT_A 8
2622 #define DUK_BC_SHIFT_B 16
2623 #define DUK_BC_SHIFT_C 24
2624 #define DUK_BC_SHIFT_BC DUK_BC_SHIFT_B
2625 #define DUK_BC_SHIFT_ABC DUK_BC_SHIFT_A
2626 
2627 #define DUK_BC_UNSHIFTED_MASK_OP 0xffUL
2628 #define DUK_BC_UNSHIFTED_MASK_A 0xffUL
2629 #define DUK_BC_UNSHIFTED_MASK_B 0xffUL
2630 #define DUK_BC_UNSHIFTED_MASK_C 0xffUL
2631 #define DUK_BC_UNSHIFTED_MASK_BC 0xffffUL
2632 #define DUK_BC_UNSHIFTED_MASK_ABC 0xffffffUL
2633 
2634 #define DUK_BC_SHIFTED_MASK_OP (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
2635 #define DUK_BC_SHIFTED_MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
2636 #define DUK_BC_SHIFTED_MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
2637 #define DUK_BC_SHIFTED_MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
2638 #define DUK_BC_SHIFTED_MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
2639 #define DUK_BC_SHIFTED_MASK_ABC (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
2640 
2641 #define DUK_DEC_OP(x) ((x) & 0xffUL)
2642 #define DUK_DEC_A(x) (((x) >> 8) & 0xffUL)
2643 #define DUK_DEC_B(x) (((x) >> 16) & 0xffUL)
2644 #define DUK_DEC_C(x) (((x) >> 24) & 0xffUL)
2645 #define DUK_DEC_BC(x) (((x) >> 16) & 0xffffUL)
2646 #define DUK_DEC_ABC(x) (((x) >> 8) & 0xffffffUL)
2647 
2648 #define DUK_ENC_OP(op) ((duk_instr_t) (op))
2649 #define DUK_ENC_OP_ABC(op,abc) ((duk_instr_t) ( \
2650  (((duk_instr_t) (abc)) << 8) | \
2651  ((duk_instr_t) (op)) \
2652  ))
2653 #define DUK_ENC_OP_A_BC(op,a,bc) ((duk_instr_t) ( \
2654  (((duk_instr_t) (bc)) << 16) | \
2655  (((duk_instr_t) (a)) << 8) | \
2656  ((duk_instr_t) (op)) \
2657  ))
2658 #define DUK_ENC_OP_A_B_C(op,a,b,c) ((duk_instr_t) ( \
2659  (((duk_instr_t) (c)) << 24) | \
2660  (((duk_instr_t) (b)) << 16) | \
2661  (((duk_instr_t) (a)) << 8) | \
2662  ((duk_instr_t) (op)) \
2663  ))
2664 #define DUK_ENC_OP_A_B(op,a,b) DUK_ENC_OP_A_B_C((op),(a),(b),0)
2665 #define DUK_ENC_OP_A(op,a) DUK_ENC_OP_A_B_C((op),(a),0,0)
2666 #define DUK_ENC_OP_BC(op,bc) DUK_ENC_OP_A_BC((op),0,(bc))
2667 
2668 /* Get opcode base value with B/C reg/const flags cleared. */
2669 #define DUK_BC_NOREGCONST_OP(op) ((op) & 0xfc)
2670 
2671 /* Constants should be signed so that signed arithmetic involving them
2672  * won't cause values to be coerced accidentally to unsigned.
2673  */
2674 #define DUK_BC_OP_MIN 0
2675 #define DUK_BC_OP_MAX 0xffL
2676 #define DUK_BC_A_MIN 0
2677 #define DUK_BC_A_MAX 0xffL
2678 #define DUK_BC_B_MIN 0
2679 #define DUK_BC_B_MAX 0xffL
2680 #define DUK_BC_C_MIN 0
2681 #define DUK_BC_C_MAX 0xffL
2682 #define DUK_BC_BC_MIN 0
2683 #define DUK_BC_BC_MAX 0xffffL
2684 #define DUK_BC_ABC_MIN 0
2685 #define DUK_BC_ABC_MAX 0xffffffL
2686 
2687 /* Masks for B/C reg/const indicator in opcode field. */
2688 #define DUK_BC_REGCONST_B (0x01UL)
2689 #define DUK_BC_REGCONST_C (0x02UL)
2690 
2691 /* Misc. masks for opcode field. */
2692 #define DUK_BC_INCDECP_FLAG_DEC (0x04UL)
2693 #define DUK_BC_INCDECP_FLAG_POST (0x08UL)
2694 
2695 /* Opcodes. */
2696 #define DUK_OP_LDREG 0
2697 #define DUK_OP_STREG 1
2698 #define DUK_OP_LDCONST 2
2699 #define DUK_OP_LDINT 3
2700 #define DUK_OP_LDINTX 4
2701 #define DUK_OP_LDTHIS 5
2702 #define DUK_OP_LDUNDEF 6
2703 #define DUK_OP_LDNULL 7
2704 #define DUK_OP_LDTRUE 8
2705 #define DUK_OP_LDFALSE 9
2706 #define DUK_OP_BNOT 10
2707 #define DUK_OP_LNOT 11
2708 #define DUK_OP_UNM 12
2709 #define DUK_OP_UNP 13
2710 #define DUK_OP_TYPEOF 14
2711 #define DUK_OP_TYPEOFID 15
2712 #define DUK_OP_EQ 16
2713 #define DUK_OP_EQ_RR 16
2714 #define DUK_OP_EQ_CR 17
2715 #define DUK_OP_EQ_RC 18
2716 #define DUK_OP_EQ_CC 19
2717 #define DUK_OP_NEQ 20
2718 #define DUK_OP_NEQ_RR 20
2719 #define DUK_OP_NEQ_CR 21
2720 #define DUK_OP_NEQ_RC 22
2721 #define DUK_OP_NEQ_CC 23
2722 #define DUK_OP_SEQ 24
2723 #define DUK_OP_SEQ_RR 24
2724 #define DUK_OP_SEQ_CR 25
2725 #define DUK_OP_SEQ_RC 26
2726 #define DUK_OP_SEQ_CC 27
2727 #define DUK_OP_SNEQ 28
2728 #define DUK_OP_SNEQ_RR 28
2729 #define DUK_OP_SNEQ_CR 29
2730 #define DUK_OP_SNEQ_RC 30
2731 #define DUK_OP_SNEQ_CC 31
2732 #define DUK_OP_GT 32
2733 #define DUK_OP_GT_RR 32
2734 #define DUK_OP_GT_CR 33
2735 #define DUK_OP_GT_RC 34
2736 #define DUK_OP_GT_CC 35
2737 #define DUK_OP_GE 36
2738 #define DUK_OP_GE_RR 36
2739 #define DUK_OP_GE_CR 37
2740 #define DUK_OP_GE_RC 38
2741 #define DUK_OP_GE_CC 39
2742 #define DUK_OP_LT 40
2743 #define DUK_OP_LT_RR 40
2744 #define DUK_OP_LT_CR 41
2745 #define DUK_OP_LT_RC 42
2746 #define DUK_OP_LT_CC 43
2747 #define DUK_OP_LE 44
2748 #define DUK_OP_LE_RR 44
2749 #define DUK_OP_LE_CR 45
2750 #define DUK_OP_LE_RC 46
2751 #define DUK_OP_LE_CC 47
2752 #define DUK_OP_IFTRUE 48
2753 #define DUK_OP_IFTRUE_R 48
2754 #define DUK_OP_IFTRUE_C 49
2755 #define DUK_OP_IFFALSE 50
2756 #define DUK_OP_IFFALSE_R 50
2757 #define DUK_OP_IFFALSE_C 51
2758 #define DUK_OP_ADD 52
2759 #define DUK_OP_ADD_RR 52
2760 #define DUK_OP_ADD_CR 53
2761 #define DUK_OP_ADD_RC 54
2762 #define DUK_OP_ADD_CC 55
2763 #define DUK_OP_SUB 56
2764 #define DUK_OP_SUB_RR 56
2765 #define DUK_OP_SUB_CR 57
2766 #define DUK_OP_SUB_RC 58
2767 #define DUK_OP_SUB_CC 59
2768 #define DUK_OP_MUL 60
2769 #define DUK_OP_MUL_RR 60
2770 #define DUK_OP_MUL_CR 61
2771 #define DUK_OP_MUL_RC 62
2772 #define DUK_OP_MUL_CC 63
2773 #define DUK_OP_DIV 64
2774 #define DUK_OP_DIV_RR 64
2775 #define DUK_OP_DIV_CR 65
2776 #define DUK_OP_DIV_RC 66
2777 #define DUK_OP_DIV_CC 67
2778 #define DUK_OP_MOD 68
2779 #define DUK_OP_MOD_RR 68
2780 #define DUK_OP_MOD_CR 69
2781 #define DUK_OP_MOD_RC 70
2782 #define DUK_OP_MOD_CC 71
2783 #define DUK_OP_EXP 72
2784 #define DUK_OP_EXP_RR 72
2785 #define DUK_OP_EXP_CR 73
2786 #define DUK_OP_EXP_RC 74
2787 #define DUK_OP_EXP_CC 75
2788 #define DUK_OP_BAND 76
2789 #define DUK_OP_BAND_RR 76
2790 #define DUK_OP_BAND_CR 77
2791 #define DUK_OP_BAND_RC 78
2792 #define DUK_OP_BAND_CC 79
2793 #define DUK_OP_BOR 80
2794 #define DUK_OP_BOR_RR 80
2795 #define DUK_OP_BOR_CR 81
2796 #define DUK_OP_BOR_RC 82
2797 #define DUK_OP_BOR_CC 83
2798 #define DUK_OP_BXOR 84
2799 #define DUK_OP_BXOR_RR 84
2800 #define DUK_OP_BXOR_CR 85
2801 #define DUK_OP_BXOR_RC 86
2802 #define DUK_OP_BXOR_CC 87
2803 #define DUK_OP_BASL 88
2804 #define DUK_OP_BASL_RR 88
2805 #define DUK_OP_BASL_CR 89
2806 #define DUK_OP_BASL_RC 90
2807 #define DUK_OP_BASL_CC 91
2808 #define DUK_OP_BLSR 92
2809 #define DUK_OP_BLSR_RR 92
2810 #define DUK_OP_BLSR_CR 93
2811 #define DUK_OP_BLSR_RC 94
2812 #define DUK_OP_BLSR_CC 95
2813 #define DUK_OP_BASR 96
2814 #define DUK_OP_BASR_RR 96
2815 #define DUK_OP_BASR_CR 97
2816 #define DUK_OP_BASR_RC 98
2817 #define DUK_OP_BASR_CC 99
2818 #define DUK_OP_INSTOF 100
2819 #define DUK_OP_INSTOF_RR 100
2820 #define DUK_OP_INSTOF_CR 101
2821 #define DUK_OP_INSTOF_RC 102
2822 #define DUK_OP_INSTOF_CC 103
2823 #define DUK_OP_IN 104
2824 #define DUK_OP_IN_RR 104
2825 #define DUK_OP_IN_CR 105
2826 #define DUK_OP_IN_RC 106
2827 #define DUK_OP_IN_CC 107
2828 #define DUK_OP_GETPROP 108
2829 #define DUK_OP_GETPROP_RR 108
2830 #define DUK_OP_GETPROP_CR 109
2831 #define DUK_OP_GETPROP_RC 110
2832 #define DUK_OP_GETPROP_CC 111
2833 #define DUK_OP_PUTPROP 112
2834 #define DUK_OP_PUTPROP_RR 112
2835 #define DUK_OP_PUTPROP_CR 113
2836 #define DUK_OP_PUTPROP_RC 114
2837 #define DUK_OP_PUTPROP_CC 115
2838 #define DUK_OP_DELPROP 116
2839 #define DUK_OP_DELPROP_RR 116
2840 #define DUK_OP_DELPROP_CR_UNUSED 117 /* unused now */
2841 #define DUK_OP_DELPROP_RC 118
2842 #define DUK_OP_DELPROP_CC_UNUSED 119 /* unused now */
2843 #define DUK_OP_PREINCR 120 /* pre/post opcode values have constraints, */
2844 #define DUK_OP_PREDECR 121 /* see duk_js_executor.c and duk_js_compiler.c. */
2845 #define DUK_OP_POSTINCR 122
2846 #define DUK_OP_POSTDECR 123
2847 #define DUK_OP_PREINCV 124
2848 #define DUK_OP_PREDECV 125
2849 #define DUK_OP_POSTINCV 126
2850 #define DUK_OP_POSTDECV 127
2851 #define DUK_OP_PREINCP 128 /* pre/post inc/dec prop opcodes have constraints */
2852 #define DUK_OP_PREINCP_RR 128
2853 #define DUK_OP_PREINCP_CR 129
2854 #define DUK_OP_PREINCP_RC 130
2855 #define DUK_OP_PREINCP_CC 131
2856 #define DUK_OP_PREDECP 132
2857 #define DUK_OP_PREDECP_RR 132
2858 #define DUK_OP_PREDECP_CR 133
2859 #define DUK_OP_PREDECP_RC 134
2860 #define DUK_OP_PREDECP_CC 135
2861 #define DUK_OP_POSTINCP 136
2862 #define DUK_OP_POSTINCP_RR 136
2863 #define DUK_OP_POSTINCP_CR 137
2864 #define DUK_OP_POSTINCP_RC 138
2865 #define DUK_OP_POSTINCP_CC 139
2866 #define DUK_OP_POSTDECP 140
2867 #define DUK_OP_POSTDECP_RR 140
2868 #define DUK_OP_POSTDECP_CR 141
2869 #define DUK_OP_POSTDECP_RC 142
2870 #define DUK_OP_POSTDECP_CC 143
2871 #define DUK_OP_DECLVAR 144
2872 #define DUK_OP_DECLVAR_RR 144
2873 #define DUK_OP_DECLVAR_CR 145
2874 #define DUK_OP_DECLVAR_RC 146
2875 #define DUK_OP_DECLVAR_CC 147
2876 #define DUK_OP_REGEXP 148
2877 #define DUK_OP_REGEXP_RR 148
2878 #define DUK_OP_REGEXP_CR 149
2879 #define DUK_OP_REGEXP_RC 150
2880 #define DUK_OP_REGEXP_CC 151
2881 #define DUK_OP_CSVAR 152
2882 #define DUK_OP_CSVAR_RR 152
2883 #define DUK_OP_CSVAR_CR 153
2884 #define DUK_OP_CSVAR_RC 154
2885 #define DUK_OP_CSVAR_CC 155
2886 #define DUK_OP_CLOSURE 156
2887 #define DUK_OP_GETVAR 157
2888 #define DUK_OP_PUTVAR 158
2889 #define DUK_OP_DELVAR 159
2890 #define DUK_OP_JUMP 160
2891 #define DUK_OP_RETREG 161
2892 #define DUK_OP_RETUNDEF 162
2893 #define DUK_OP_RETCONST 163
2894 #define DUK_OP_RETCONSTN 164 /* return const without incref (e.g. number) */
2895 #define DUK_OP_LABEL 165
2896 #define DUK_OP_ENDLABEL 166
2897 #define DUK_OP_BREAK 167
2898 #define DUK_OP_CONTINUE 168
2899 #define DUK_OP_TRYCATCH 169
2900 #define DUK_OP_ENDTRY 170
2901 #define DUK_OP_ENDCATCH 171
2902 #define DUK_OP_ENDFIN 172
2903 #define DUK_OP_THROW 173
2904 #define DUK_OP_CSREG 174
2905 #define DUK_OP_EVALCALL 175
2906 #define DUK_OP_CALL 176 /* must be even */
2907 #define DUK_OP_TAILCALL 177 /* must be odd */
2908 #define DUK_OP_NEW 178
2909 #define DUK_OP_NEWOBJ 179
2910 #define DUK_OP_NEWARR 180
2911 #define DUK_OP_MPUTOBJ 181
2912 #define DUK_OP_MPUTOBJI 182
2913 #define DUK_OP_INITSET 183
2914 #define DUK_OP_INITGET 184
2915 #define DUK_OP_MPUTARR 185
2916 #define DUK_OP_MPUTARRI 186
2917 #define DUK_OP_SETALEN 187
2918 #define DUK_OP_INITENUM 188
2919 #define DUK_OP_NEXTENUM 189
2920 #define DUK_OP_INVLHS 190
2921 #define DUK_OP_DEBUGGER 191
2922 #define DUK_OP_NOP 192
2923 #define DUK_OP_INVALID 193
2924 #define DUK_OP_UNUSED194 194
2925 #define DUK_OP_UNUSED195 195
2926 #define DUK_OP_UNUSED196 196
2927 #define DUK_OP_UNUSED197 197
2928 #define DUK_OP_UNUSED198 198
2929 #define DUK_OP_UNUSED199 199
2930 #define DUK_OP_UNUSED200 200
2931 #define DUK_OP_UNUSED201 201
2932 #define DUK_OP_UNUSED202 202
2933 #define DUK_OP_UNUSED203 203
2934 #define DUK_OP_UNUSED204 204
2935 #define DUK_OP_UNUSED205 205
2936 #define DUK_OP_UNUSED206 206
2937 #define DUK_OP_UNUSED207 207
2938 #define DUK_OP_UNUSED208 208
2939 #define DUK_OP_UNUSED209 209
2940 #define DUK_OP_UNUSED210 210
2941 #define DUK_OP_UNUSED211 211
2942 #define DUK_OP_UNUSED212 212
2943 #define DUK_OP_UNUSED213 213
2944 #define DUK_OP_UNUSED214 214
2945 #define DUK_OP_UNUSED215 215
2946 #define DUK_OP_UNUSED216 216
2947 #define DUK_OP_UNUSED217 217
2948 #define DUK_OP_UNUSED218 218
2949 #define DUK_OP_UNUSED219 219
2950 #define DUK_OP_UNUSED220 220
2951 #define DUK_OP_UNUSED221 221
2952 #define DUK_OP_UNUSED222 222
2953 #define DUK_OP_UNUSED223 223
2954 #define DUK_OP_UNUSED224 224
2955 #define DUK_OP_UNUSED225 225
2956 #define DUK_OP_UNUSED226 226
2957 #define DUK_OP_UNUSED227 227
2958 #define DUK_OP_UNUSED228 228
2959 #define DUK_OP_UNUSED229 229
2960 #define DUK_OP_UNUSED230 230
2961 #define DUK_OP_UNUSED231 231
2962 #define DUK_OP_UNUSED232 232
2963 #define DUK_OP_UNUSED233 233
2964 #define DUK_OP_UNUSED234 234
2965 #define DUK_OP_UNUSED235 235
2966 #define DUK_OP_UNUSED236 236
2967 #define DUK_OP_UNUSED237 237
2968 #define DUK_OP_UNUSED238 238
2969 #define DUK_OP_UNUSED239 239
2970 #define DUK_OP_UNUSED240 240
2971 #define DUK_OP_UNUSED241 241
2972 #define DUK_OP_UNUSED242 242
2973 #define DUK_OP_UNUSED243 243
2974 #define DUK_OP_UNUSED244 244
2975 #define DUK_OP_UNUSED245 245
2976 #define DUK_OP_UNUSED246 246
2977 #define DUK_OP_UNUSED247 247
2978 #define DUK_OP_UNUSED248 248
2979 #define DUK_OP_UNUSED249 249
2980 #define DUK_OP_UNUSED250 250
2981 #define DUK_OP_UNUSED251 251
2982 #define DUK_OP_UNUSED252 252
2983 #define DUK_OP_UNUSED253 253
2984 #define DUK_OP_UNUSED254 254
2985 #define DUK_OP_UNUSED255 255
2986 #define DUK_OP_NONE 256 /* dummy value used as marker (doesn't fit in 8-bit field) */
2987 
2988 /* XXX: Allocate flags from opcode field? Would take 16 opcode slots
2989  * but avoids shuffling in more cases. Maybe not worth it.
2990  */
2991 /* DUK_OP_TRYCATCH flags in A */
2992 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH (1 << 0)
2993 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY (1 << 1)
2994 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING (1 << 2)
2995 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING (1 << 3)
2996 
2997 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags (DUK_PROPDESC_FLAG_XXX) */
2998 #define DUK_BC_DECLVAR_FLAG_UNDEF_VALUE (1 << 4) /* use 'undefined' for value automatically */
2999 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL (1 << 5) /* function declaration */
3000 
3001 /* Misc constants and helper macros. */
3002 #define DUK_BC_LDINT_BIAS (1L << 15)
3003 #define DUK_BC_LDINTX_SHIFT 16
3004 #define DUK_BC_JUMP_BIAS (1L << 23)
3005 
3006 #endif /* DUK_JS_BYTECODE_H_INCLUDED */
3007 /* #include duk_lexer.h */
3008 /*
3009  * Lexer defines.
3010  */
3011 
3012 #if !defined(DUK_LEXER_H_INCLUDED)
3013 #define DUK_LEXER_H_INCLUDED
3014 
3015 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3016 
3017 /*
3018  * A token is interpreted as any possible production of InputElementDiv
3019  * and InputElementRegExp, see E5 Section 7 in its entirety. Note that
3020  * the E5 "Token" production does not cover all actual tokens of the
3021  * language (which is explicitly stated in the specification, Section 7.5).
3022  * Null and boolean literals are defined as part of both ReservedWord
3023  * (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions. Here,
3024  * null and boolean values have literal tokens, and are not reserved
3025  * words.
3026  *
3027  * Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3028  * The number tokens always have a non-negative value. The unary minus
3029  * operator in "-1.0" is optimized during compilation to yield a single
3030  * negative constant.
3031  *
3032  * Token numbering is free except that reserved words are required to be
3033  * in a continuous range and in a particular order. See genstrings.py.
3034  */
3035 
3036 #define DUK_LEXER_INITCTX(ctx) duk_lexer_initctx((ctx))
3037 
3038 #define DUK_LEXER_SETPOINT(ctx,pt) duk_lexer_setpoint((ctx), (pt))
3039 
3040 #define DUK_LEXER_GETPOINT(ctx,pt) duk_lexer_getpoint((ctx), (pt))
3041 
3042 /* currently 6 characters of lookup are actually needed (duk_lexer.c) */
3043 #define DUK_LEXER_WINDOW_SIZE 6
3044 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3045 #define DUK_LEXER_BUFFER_SIZE 64
3046 #endif
3047 
3048 #define DUK_TOK_MINVAL 0
3049 
3050 /* returned after EOF (infinite amount) */
3051 #define DUK_TOK_EOF 0
3052 
3053 /* identifier names (E5 Section 7.6) */
3054 #define DUK_TOK_IDENTIFIER 1
3055 
3056 /* reserved words: keywords */
3057 #define DUK_TOK_START_RESERVED 2
3058 #define DUK_TOK_BREAK 2
3059 #define DUK_TOK_CASE 3
3060 #define DUK_TOK_CATCH 4
3061 #define DUK_TOK_CONTINUE 5
3062 #define DUK_TOK_DEBUGGER 6
3063 #define DUK_TOK_DEFAULT 7
3064 #define DUK_TOK_DELETE 8
3065 #define DUK_TOK_DO 9
3066 #define DUK_TOK_ELSE 10
3067 #define DUK_TOK_FINALLY 11
3068 #define DUK_TOK_FOR 12
3069 #define DUK_TOK_FUNCTION 13
3070 #define DUK_TOK_IF 14
3071 #define DUK_TOK_IN 15
3072 #define DUK_TOK_INSTANCEOF 16
3073 #define DUK_TOK_NEW 17
3074 #define DUK_TOK_RETURN 18
3075 #define DUK_TOK_SWITCH 19
3076 #define DUK_TOK_THIS 20
3077 #define DUK_TOK_THROW 21
3078 #define DUK_TOK_TRY 22
3079 #define DUK_TOK_TYPEOF 23
3080 #define DUK_TOK_VAR 24
3081 #define DUK_TOK_CONST 25
3082 #define DUK_TOK_VOID 26
3083 #define DUK_TOK_WHILE 27
3084 #define DUK_TOK_WITH 28
3085 
3086 /* reserved words: future reserved words */
3087 #define DUK_TOK_CLASS 29
3088 #define DUK_TOK_ENUM 30
3089 #define DUK_TOK_EXPORT 31
3090 #define DUK_TOK_EXTENDS 32
3091 #define DUK_TOK_IMPORT 33
3092 #define DUK_TOK_SUPER 34
3093 
3094 /* "null", "true", and "false" are always reserved words.
3095  * Note that "get" and "set" are not!
3096  */
3097 #define DUK_TOK_NULL 35
3098 #define DUK_TOK_TRUE 36
3099 #define DUK_TOK_FALSE 37
3100 
3101 /* reserved words: additional future reserved words in strict mode */
3102 #define DUK_TOK_START_STRICT_RESERVED 38 /* inclusive */
3103 #define DUK_TOK_IMPLEMENTS 38
3104 #define DUK_TOK_INTERFACE 39
3105 #define DUK_TOK_LET 40
3106 #define DUK_TOK_PACKAGE 41
3107 #define DUK_TOK_PRIVATE 42
3108 #define DUK_TOK_PROTECTED 43
3109 #define DUK_TOK_PUBLIC 44
3110 #define DUK_TOK_STATIC 45
3111 #define DUK_TOK_YIELD 46
3112 
3113 #define DUK_TOK_END_RESERVED 47 /* exclusive */
3114 
3115 /* "get" and "set" are tokens but NOT ReservedWords. They are currently
3116  * parsed and identifiers and these defines are actually now unused.
3117  */
3118 #define DUK_TOK_GET 47
3119 #define DUK_TOK_SET 48
3120 
3121 /* punctuators (unlike the spec, also includes "/" and "/=") */
3122 #define DUK_TOK_LCURLY 49
3123 #define DUK_TOK_RCURLY 50
3124 #define DUK_TOK_LBRACKET 51
3125 #define DUK_TOK_RBRACKET 52
3126 #define DUK_TOK_LPAREN 53
3127 #define DUK_TOK_RPAREN 54
3128 #define DUK_TOK_PERIOD 55
3129 #define DUK_TOK_SEMICOLON 56
3130 #define DUK_TOK_COMMA 57
3131 #define DUK_TOK_LT 58
3132 #define DUK_TOK_GT 59
3133 #define DUK_TOK_LE 60
3134 #define DUK_TOK_GE 61
3135 #define DUK_TOK_EQ 62
3136 #define DUK_TOK_NEQ 63
3137 #define DUK_TOK_SEQ 64
3138 #define DUK_TOK_SNEQ 65
3139 #define DUK_TOK_ADD 66
3140 #define DUK_TOK_SUB 67
3141 #define DUK_TOK_MUL 68
3142 #define DUK_TOK_DIV 69
3143 #define DUK_TOK_MOD 70
3144 #define DUK_TOK_EXP 71
3145 #define DUK_TOK_INCREMENT 72
3146 #define DUK_TOK_DECREMENT 73
3147 #define DUK_TOK_ALSHIFT 74 /* named "arithmetic" because result is signed */
3148 #define DUK_TOK_ARSHIFT 75
3149 #define DUK_TOK_RSHIFT 76
3150 #define DUK_TOK_BAND 77
3151 #define DUK_TOK_BOR 78
3152 #define DUK_TOK_BXOR 79
3153 #define DUK_TOK_LNOT 80
3154 #define DUK_TOK_BNOT 81
3155 #define DUK_TOK_LAND 82
3156 #define DUK_TOK_LOR 83
3157 #define DUK_TOK_QUESTION 84
3158 #define DUK_TOK_COLON 85
3159 #define DUK_TOK_EQUALSIGN 86
3160 #define DUK_TOK_ADD_EQ 87
3161 #define DUK_TOK_SUB_EQ 88
3162 #define DUK_TOK_MUL_EQ 89
3163 #define DUK_TOK_DIV_EQ 90
3164 #define DUK_TOK_MOD_EQ 91
3165 #define DUK_TOK_EXP_EQ 92
3166 #define DUK_TOK_ALSHIFT_EQ 93
3167 #define DUK_TOK_ARSHIFT_EQ 94
3168 #define DUK_TOK_RSHIFT_EQ 95
3169 #define DUK_TOK_BAND_EQ 96
3170 #define DUK_TOK_BOR_EQ 97
3171 #define DUK_TOK_BXOR_EQ 98
3172 
3173 /* literals (E5 Section 7.8), except null, true, false, which are treated
3174  * like reserved words (above).
3175  */
3176 #define DUK_TOK_NUMBER 99
3177 #define DUK_TOK_STRING 100
3178 #define DUK_TOK_REGEXP 101
3179 
3180 #define DUK_TOK_MAXVAL 101 /* inclusive */
3181 
3182 /* Convert heap string index to a token (reserved words) */
3183 #define DUK_STRIDX_TO_TOK(x) ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3184 
3185 /* Sanity check */
3186 #if (DUK_TOK_MAXVAL > 255)
3187 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3188 #endif
3189 
3190 /* Sanity checks for string and token defines */
3191 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3192 #error mismatch in token defines
3193 #endif
3194 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3195 #error mismatch in token defines
3196 #endif
3197 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3198 #error mismatch in token defines
3199 #endif
3200 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3201 #error mismatch in token defines
3202 #endif
3203 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3204 #error mismatch in token defines
3205 #endif
3206 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3207 #error mismatch in token defines
3208 #endif
3209 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3210 #error mismatch in token defines
3211 #endif
3212 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3213 #error mismatch in token defines
3214 #endif
3215 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3216 #error mismatch in token defines
3217 #endif
3218 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3219 #error mismatch in token defines
3220 #endif
3221 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3222 #error mismatch in token defines
3223 #endif
3224 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3225 #error mismatch in token defines
3226 #endif
3227 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3228 #error mismatch in token defines
3229 #endif
3230 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3231 #error mismatch in token defines
3232 #endif
3233 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3234 #error mismatch in token defines
3235 #endif
3236 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3237 #error mismatch in token defines
3238 #endif
3239 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3240 #error mismatch in token defines
3241 #endif
3242 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3243 #error mismatch in token defines
3244 #endif
3245 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3246 #error mismatch in token defines
3247 #endif
3248 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3249 #error mismatch in token defines
3250 #endif
3251 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3252 #error mismatch in token defines
3253 #endif
3254 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3255 #error mismatch in token defines
3256 #endif
3257 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3258 #error mismatch in token defines
3259 #endif
3260 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3261 #error mismatch in token defines
3262 #endif
3263 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3264 #error mismatch in token defines
3265 #endif
3266 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3267 #error mismatch in token defines
3268 #endif
3269 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3270 #error mismatch in token defines
3271 #endif
3272 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3273 #error mismatch in token defines
3274 #endif
3275 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3276 #error mismatch in token defines
3277 #endif
3278 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3279 #error mismatch in token defines
3280 #endif
3281 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3282 #error mismatch in token defines
3283 #endif
3284 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3285 #error mismatch in token defines
3286 #endif
3287 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3288 #error mismatch in token defines
3289 #endif
3290 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3291 #error mismatch in token defines
3292 #endif
3293 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3294 #error mismatch in token defines
3295 #endif
3296 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3297 #error mismatch in token defines
3298 #endif
3299 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3300 #error mismatch in token defines
3301 #endif
3302 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3303 #error mismatch in token defines
3304 #endif
3305 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3306 #error mismatch in token defines
3307 #endif
3308 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3309 #error mismatch in token defines
3310 #endif
3311 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3312 #error mismatch in token defines
3313 #endif
3314 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3315 #error mismatch in token defines
3316 #endif
3317 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3318 #error mismatch in token defines
3319 #endif
3320 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3321 #error mismatch in token defines
3322 #endif
3323 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3324 #error mismatch in token defines
3325 #endif
3326 
3327 /* Regexp tokens */
3328 #define DUK_RETOK_EOF 0
3329 #define DUK_RETOK_DISJUNCTION 1
3330 #define DUK_RETOK_QUANTIFIER 2
3331 #define DUK_RETOK_ASSERT_START 3
3332 #define DUK_RETOK_ASSERT_END 4
3333 #define DUK_RETOK_ASSERT_WORD_BOUNDARY 5
3334 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY 6
3335 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD 7
3336 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD 8
3337 #define DUK_RETOK_ATOM_PERIOD 9
3338 #define DUK_RETOK_ATOM_CHAR 10
3339 #define DUK_RETOK_ATOM_DIGIT 11 /* assumptions in regexp compiler */
3340 #define DUK_RETOK_ATOM_NOT_DIGIT 12 /* -""- */
3341 #define DUK_RETOK_ATOM_WHITE 13 /* -""- */
3342 #define DUK_RETOK_ATOM_NOT_WHITE 14 /* -""- */
3343 #define DUK_RETOK_ATOM_WORD_CHAR 15 /* -""- */
3344 #define DUK_RETOK_ATOM_NOT_WORD_CHAR 16 /* -""- */
3345 #define DUK_RETOK_ATOM_BACKREFERENCE 17
3346 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP 18
3347 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP 19
3348 #define DUK_RETOK_ATOM_START_CHARCLASS 20
3349 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED 21
3350 #define DUK_RETOK_ATOM_END_GROUP 22
3351 
3352 /* Constants for duk_lexer_ctx.buf. */
3353 #define DUK_LEXER_TEMP_BUF_LIMIT 256
3354 
3355 /* A token value. Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3356  * Some fields (like num, str1, str2) are only valid for specific token types and may have
3357  * stale values otherwise.
3358  */
3359 struct duk_token {
3360  duk_small_int_t t; /* token type (with reserved word identification) */
3361  duk_small_int_t t_nores; /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3362  duk_double_t num; /* numeric value of token */
3363  duk_hstring *str1; /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3364  duk_hstring *str2; /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3365  duk_size_t start_offset; /* start byte offset of token in lexer input */
3366  duk_int_t start_line; /* start line of token (first char) */
3367  duk_int_t num_escapes; /* number of escapes and line continuations (for directive prologue) */
3368  duk_bool_t lineterm; /* token was preceded by a lineterm */
3369  duk_bool_t allow_auto_semi; /* token allows automatic semicolon insertion (eof or preceded by newline) */
3370 };
3371 
3372 #define DUK_RE_QUANTIFIER_INFINITE ((duk_uint32_t) 0xffffffffUL)
3373 
3374 /* A regexp token value. */
3376  duk_small_int_t t; /* token type */
3377  duk_small_int_t greedy;
3378  duk_uint_fast32_t num; /* numeric value (character, count) */
3379  duk_uint_fast32_t qmin;
3380  duk_uint_fast32_t qmax;
3381 };
3382 
3383 /* A structure for 'snapshotting' a point for rewinding */
3385  duk_size_t offset;
3386  duk_int_t line;
3387 };
3388 
3389 /* Lexer codepoint with additional info like offset/line number */
3391  duk_codepoint_t codepoint;
3392  duk_size_t offset;
3393  duk_int_t line;
3394 };
3395 
3396 /* Lexer context. Same context is used for Ecmascript and Regexp parsing. */
3398 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3399  duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
3400  duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
3401 #else
3402  duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
3403 #endif
3404 
3405  duk_hthread *thr; /* thread; minimizes argument passing */
3406 
3407  const duk_uint8_t *input; /* input string (may be a user pointer) */
3408  duk_size_t input_length; /* input byte length */
3409  duk_size_t input_offset; /* input offset for window leading edge (not window[0]) */
3410  duk_int_t input_line; /* input linenumber at input_offset (not window[0]), init to 1 */
3411 
3412  duk_idx_t slot1_idx; /* valstack slot for 1st token value */
3413  duk_idx_t slot2_idx; /* valstack slot for 2nd token value */
3414  duk_idx_t buf_idx; /* valstack slot for temp buffer */
3415  duk_hbuffer_dynamic *buf; /* temp accumulation buffer */
3416  duk_bufwriter_ctx bw; /* bufwriter for temp accumulation */
3417 
3418  duk_int_t token_count; /* number of tokens parsed */
3419  duk_int_t token_limit; /* maximum token count before error (sanity backstop) */
3420 };
3421 
3422 /*
3423  * Prototypes
3424  */
3425 
3426 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
3427 
3428 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
3429 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
3430 
3431 DUK_INTERNAL_DECL
3432 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
3433  duk_token *out_token,
3434  duk_bool_t strict_mode,
3435  duk_bool_t regexp_mode);
3436 #if defined(DUK_USE_REGEXP_SUPPORT)
3437 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
3438 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
3439 #endif /* DUK_USE_REGEXP_SUPPORT */
3440 
3441 #endif /* DUK_LEXER_H_INCLUDED */
3442 /* #include duk_js_compiler.h */
3443 /*
3444  * Ecmascript compiler.
3445  */
3446 
3447 #if !defined(DUK_JS_COMPILER_H_INCLUDED)
3448 #define DUK_JS_COMPILER_H_INCLUDED
3449 
3450 /* ecmascript compiler limits */
3451 #define DUK_COMPILER_TOKEN_LIMIT 100000000L /* 1e8: protects against deeply nested inner functions */
3452 
3453 /* maximum loopcount for peephole optimization */
3454 #define DUK_COMPILER_PEEPHOLE_MAXITER 3
3455 
3456 /* maximum bytecode length in instructions */
3457 #define DUK_COMPILER_MAX_BYTECODE_LENGTH (256L * 1024L * 1024L) /* 1 GB */
3458 
3459 /*
3460  * Compiler intermediate values
3461  *
3462  * Intermediate values describe either plain values (e.g. strings or
3463  * numbers) or binary operations which have not yet been coerced into
3464  * either a left-hand-side or right-hand-side role (e.g. object property).
3465  */
3466 
3467 #define DUK_IVAL_NONE 0 /* no value */
3468 #define DUK_IVAL_PLAIN 1 /* register, constant, or value */
3469 #define DUK_IVAL_ARITH 2 /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */
3470 #define DUK_IVAL_PROP 3 /* property access */
3471 #define DUK_IVAL_VAR 4 /* variable access */
3472 
3473 #define DUK_ISPEC_NONE 0 /* no value */
3474 #define DUK_ISPEC_VALUE 1 /* value resides in 'valstack_idx' */
3475 #define DUK_ISPEC_REGCONST 2 /* value resides in a register or constant */
3476 
3477 /* Bit mask which indicates that a regconst is a constant instead of a register.
3478  * Chosen so that when a regconst is cast to duk_int32_t, all consts are
3479  * negative values.
3480  */
3481 #define DUK_REGCONST_CONST_MARKER 0x80000000UL
3482 
3483 /* type to represent a reg/const reference during compilation */
3484 typedef duk_uint32_t duk_regconst_t;
3485 
3486 /* type to represent a straight register reference, with <0 indicating none */
3487 typedef duk_int32_t duk_reg_t;
3488 
3489 typedef struct {
3490  duk_small_uint_t t; /* DUK_ISPEC_XXX */
3491  duk_regconst_t regconst;
3492  duk_idx_t valstack_idx; /* always set; points to a reserved valstack slot */
3493 } duk_ispec;
3494 
3495 typedef struct {
3496  /*
3497  * PLAIN: x1
3498  * ARITH: x1 <op> x2
3499  * PROP: x1.x2
3500  * VAR: x1 (name)
3501  */
3502 
3503  /* XXX: can be optimized for smaller footprint esp. on 32-bit environments */
3504  duk_small_uint_t t; /* DUK_IVAL_XXX */
3505  duk_small_uint_t op; /* bytecode opcode for binary ops */
3506  duk_ispec x1;
3507  duk_ispec x2;
3508 } duk_ivalue;
3509 
3510 /*
3511  * Bytecode instruction representation during compilation
3512  *
3513  * Contains the actual instruction and (optionally) debug info.
3514  */
3515 
3517  duk_instr_t ins;
3518 #if defined(DUK_USE_PC2LINE)
3519  duk_uint32_t line;
3520 #endif
3521 };
3522 
3523 /*
3524  * Compiler state
3525  */
3526 
3527 #define DUK_LABEL_FLAG_ALLOW_BREAK (1 << 0)
3528 #define DUK_LABEL_FLAG_ALLOW_CONTINUE (1 << 1)
3529 
3530 #define DUK_DECL_TYPE_VAR 0
3531 #define DUK_DECL_TYPE_FUNC 1
3532 
3533 /* XXX: optimize to 16 bytes */
3534 typedef struct {
3535  duk_small_uint_t flags;
3536  duk_int_t label_id; /* numeric label_id (-1 reserved as marker) */
3537  duk_hstring *h_label; /* borrowed label name */
3538  duk_int_t catch_depth; /* catch depth at point of definition */
3539  duk_int_t pc_label; /* pc of label statement:
3540  * pc+1: break jump site
3541  * pc+2: continue jump site
3542  */
3543 
3544  /* Fast jumps (which avoid longjmp) jump directly to the jump sites
3545  * which are always known even while the iteration/switch statement
3546  * is still being parsed. A final peephole pass "straightens out"
3547  * the jumps.
3548  */
3549 } duk_labelinfo;
3550 
3551 /* Compiling state of one function, eventually converted to duk_hcompfunc */
3553  /* These pointers are at the start of the struct so that they pack
3554  * nicely. Mixing pointers and integer values is bad on some
3555  * platforms (e.g. if int is 32 bits and pointers are 64 bits).
3556  */
3557 
3558  duk_bufwriter_ctx bw_code; /* bufwriter for code */
3559 
3560  duk_hstring *h_name; /* function name (borrowed reference), ends up in _name */
3561  /* h_code: held in bw_code */
3562  duk_hobject *h_consts; /* array */
3563  duk_hobject *h_funcs; /* array of function templates: [func1, offset1, line1, func2, offset2, line2]
3564  * offset/line points to closing brace to allow skipping on pass 2
3565  */
3566  duk_hobject *h_decls; /* array of declarations: [ name1, val1, name2, val2, ... ]
3567  * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)
3568  * record function and variable declarations in pass 1
3569  */
3570  duk_hobject *h_labelnames; /* array of active label names */
3571  duk_hbuffer_dynamic *h_labelinfos; /* C array of duk_labelinfo */
3572  duk_hobject *h_argnames; /* array of formal argument names (-> _Formals) */
3573  duk_hobject *h_varmap; /* variable map for pass 2 (identifier -> register number or null (unmapped)) */
3574 
3575  /* Value stack indices for tracking objects. */
3576  /* code_idx: not needed */
3577  duk_idx_t consts_idx;
3578  duk_idx_t funcs_idx;
3579  duk_idx_t decls_idx;
3580  duk_idx_t labelnames_idx;
3581  duk_idx_t labelinfos_idx;
3582  duk_idx_t argnames_idx;
3583  duk_idx_t varmap_idx;
3584 
3585  /* Temp reg handling. */
3586  duk_reg_t temp_first; /* first register that is a temporary (below: variables) */
3587  duk_reg_t temp_next; /* next temporary register to allocate */
3588  duk_reg_t temp_max; /* highest value of temp_reg (temp_max - 1 is highest used reg) */
3589 
3590  /* Shuffle registers if large number of regs/consts. */
3591  duk_reg_t shuffle1;
3592  duk_reg_t shuffle2;
3593  duk_reg_t shuffle3;
3594 
3595  /* Stats for current expression being parsed. */
3596  duk_int_t nud_count;
3597  duk_int_t led_count;
3598  duk_int_t paren_level; /* parenthesis count, 0 = top level */
3599  duk_bool_t expr_lhs; /* expression is left-hand-side compatible */
3600  duk_bool_t allow_in; /* current paren level allows 'in' token */
3601 
3602  /* Misc. */
3603  duk_int_t stmt_next; /* statement id allocation (running counter) */
3604  duk_int_t label_next; /* label id allocation (running counter) */
3605  duk_int_t catch_depth; /* catch stack depth */
3606  duk_int_t with_depth; /* with stack depth (affects identifier lookups) */
3607  duk_int_t fnum_next; /* inner function numbering */
3608  duk_int_t num_formals; /* number of formal arguments */
3609  duk_reg_t reg_stmt_value; /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */
3610 #if defined(DUK_USE_DEBUGGER_SUPPORT)
3611  duk_int_t min_line; /* XXX: typing (duk_hcompfunc has duk_uint32_t) */
3612  duk_int_t max_line;
3613 #endif
3614 
3615  /* Status booleans. */
3616  duk_uint8_t is_function; /* is an actual function (not global/eval code) */
3617  duk_uint8_t is_eval; /* is eval code */
3618  duk_uint8_t is_global; /* is global code */
3619  duk_uint8_t is_namebinding; /* needs a name binding */
3620  duk_uint8_t is_constructable; /* result is constructable */
3621  duk_uint8_t is_setget; /* is a setter/getter */
3622  duk_uint8_t is_strict; /* function is strict */
3623  duk_uint8_t is_notail; /* function must not be tail called */
3624  duk_uint8_t in_directive_prologue; /* parsing in "directive prologue", recognize directives */
3625  duk_uint8_t in_scanning; /* parsing in "scanning" phase (first pass) */
3626  duk_uint8_t may_direct_eval; /* function may call direct eval */
3627  duk_uint8_t id_access_arguments; /* function refers to 'arguments' identifier */
3628  duk_uint8_t id_access_slow; /* function makes one or more slow path accesses that won't match own static variables */
3629  duk_uint8_t id_access_slow_own; /* function makes one or more slow path accesses that may match own static variables */
3630  duk_uint8_t is_arguments_shadowed; /* argument/function declaration shadows 'arguments' */
3631  duk_uint8_t needs_shuffle; /* function needs shuffle registers */
3632  duk_uint8_t reject_regexp_in_adv; /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */
3633 };
3634 
3636  duk_hthread *thr;
3637 
3638  /* filename being compiled (ends up in functions' '_filename' property) */
3639  duk_hstring *h_filename; /* borrowed reference */
3640 
3641  /* lexing (tokenization) state (contains two valstack slot indices) */
3642  duk_lexer_ctx lex;
3643 
3644  /* current and previous token for parsing */
3645  duk_token prev_token;
3646  duk_token curr_token;
3647  duk_idx_t tok11_idx; /* curr_token slot1 (matches 'lex' slot1_idx) */
3648  duk_idx_t tok12_idx; /* curr_token slot2 (matches 'lex' slot2_idx) */
3649  duk_idx_t tok21_idx; /* prev_token slot1 */
3650  duk_idx_t tok22_idx; /* prev_token slot2 */
3651 
3652  /* recursion limit */
3653  duk_int_t recursion_depth;
3654  duk_int_t recursion_limit;
3655 
3656  /* code emission temporary */
3657  duk_int_t emit_jumpslot_pc;
3658 
3659  /* current function being compiled (embedded instead of pointer for more compact access) */
3660  duk_compiler_func curr_func;
3661 };
3662 
3663 /*
3664  * Prototypes
3665  */
3666 
3667 #define DUK_JS_COMPILE_FLAG_EVAL (1 << 0) /* source is eval code (not global) */
3668 #define DUK_JS_COMPILE_FLAG_STRICT (1 << 1) /* strict outer context */
3669 #define DUK_JS_COMPILE_FLAG_FUNCEXPR (1 << 2) /* source is a function expression (used for Function constructor) */
3670 
3671 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);
3672 
3673 #endif /* DUK_JS_COMPILER_H_INCLUDED */
3674 /* #include duk_regexp.h */
3675 /*
3676  * Regular expression structs, constants, and bytecode defines.
3677  */
3678 
3679 #if !defined(DUK_REGEXP_H_INCLUDED)
3680 #define DUK_REGEXP_H_INCLUDED
3681 
3682 /* maximum bytecode copies for {n,m} quantifiers */
3683 #define DUK_RE_MAX_ATOM_COPIES 1000
3684 
3685 /* regexp compilation limits */
3686 #define DUK_RE_COMPILE_TOKEN_LIMIT 100000000L /* 1e8 */
3687 
3688 /* regexp execution limits */
3689 #define DUK_RE_EXECUTE_STEPS_LIMIT 1000000000L /* 1e9 */
3690 
3691 /* regexp opcodes */
3692 #define DUK_REOP_MATCH 1
3693 #define DUK_REOP_CHAR 2
3694 #define DUK_REOP_PERIOD 3
3695 #define DUK_REOP_RANGES 4
3696 #define DUK_REOP_INVRANGES 5
3697 #define DUK_REOP_JUMP 6
3698 #define DUK_REOP_SPLIT1 7
3699 #define DUK_REOP_SPLIT2 8
3700 #define DUK_REOP_SQMINIMAL 9
3701 #define DUK_REOP_SQGREEDY 10
3702 #define DUK_REOP_SAVE 11
3703 #define DUK_REOP_WIPERANGE 12
3704 #define DUK_REOP_LOOKPOS 13
3705 #define DUK_REOP_LOOKNEG 14
3706 #define DUK_REOP_BACKREFERENCE 15
3707 #define DUK_REOP_ASSERT_START 16
3708 #define DUK_REOP_ASSERT_END 17
3709 #define DUK_REOP_ASSERT_WORD_BOUNDARY 18
3710 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY 19
3711 
3712 /* flags */
3713 #define DUK_RE_FLAG_GLOBAL (1 << 0)
3714 #define DUK_RE_FLAG_IGNORE_CASE (1 << 1)
3715 #define DUK_RE_FLAG_MULTILINE (1 << 2)
3716 
3718  duk_hthread *thr;
3719 
3720  duk_uint32_t re_flags;
3721  const duk_uint8_t *input;
3722  const duk_uint8_t *input_end;
3723  const duk_uint8_t *bytecode;
3724  const duk_uint8_t *bytecode_end;
3725  const duk_uint8_t **saved; /* allocated from valstack (fixed buffer) */
3726  duk_uint32_t nsaved;
3727  duk_uint32_t recursion_depth;
3728  duk_uint32_t recursion_limit;
3729  duk_uint32_t steps_count;
3730  duk_uint32_t steps_limit;
3731 };
3732 
3734  duk_hthread *thr;
3735 
3736  duk_uint32_t re_flags;
3737  duk_lexer_ctx lex;
3738  duk_re_token curr_token;
3739  duk_bufwriter_ctx bw;
3740  duk_uint32_t captures; /* highest capture number emitted so far (used as: ++captures) */
3741  duk_uint32_t highest_backref;
3742  duk_uint32_t recursion_depth;
3743  duk_uint32_t recursion_limit;
3744  duk_uint32_t nranges; /* internal temporary value, used for char classes */
3745 };
3746 
3747 /*
3748  * Prototypes
3749  */
3750 
3751 #if defined(DUK_USE_REGEXP_SUPPORT)
3752 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
3753 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
3754 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
3755 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr); /* hacky helper for String.prototype.split() */
3756 #endif
3757 
3758 #endif /* DUK_REGEXP_H_INCLUDED */
3759 /* #include duk_heaphdr.h */
3760 /*
3761  * Heap header definition and assorted macros, including ref counting.
3762  * Access all fields through the accessor macros.
3763  */
3764 
3765 #if !defined(DUK_HEAPHDR_H_INCLUDED)
3766 #define DUK_HEAPHDR_H_INCLUDED
3767 
3768 /*
3769  * Common heap header
3770  *
3771  * All heap objects share the same flags and refcount fields. Objects other
3772  * than strings also need to have a single or double linked list pointers
3773  * for insertion into the "heap allocated" list. Strings are held in the
3774  * heap-wide string table so they don't need link pointers.
3775  *
3776  * Technically, 'h_refcount' must be wide enough to guarantee that it cannot
3777  * wrap (otherwise objects might be freed incorrectly after wrapping). This
3778  * means essentially that the refcount field must be as wide as data pointers.
3779  * On 64-bit platforms this means that the refcount needs to be 64 bits even
3780  * if an 'int' is 32 bits. This is a bit unfortunate, and compromising on
3781  * this might be reasonable in the future.
3782  *
3783  * Heap header size on 32-bit platforms: 8 bytes without reference counting,
3784  * 16 bytes with reference counting.
3785  */
3786 
3787 struct duk_heaphdr {
3788  duk_uint32_t h_flags;
3789 
3790 #if defined(DUK_USE_REFERENCE_COUNTING)
3791 #if defined(DUK_USE_REFCOUNT16)
3792  duk_uint16_t h_refcount16;
3793 #else
3794  duk_size_t h_refcount;
3795 #endif
3796 #endif
3797 
3798 #if defined(DUK_USE_HEAPPTR16)
3799  duk_uint16_t h_next16;
3800 #else
3801  duk_heaphdr *h_next;
3802 #endif
3803 
3804 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3805  /* refcounting requires direct heap frees, which in turn requires a dual linked heap */
3806 #if defined(DUK_USE_HEAPPTR16)
3807  duk_uint16_t h_prev16;
3808 #else
3809  duk_heaphdr *h_prev;
3810 #endif
3811 #endif
3812 
3813  /* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
3814  * struct won't align nicely to 4 bytes. This 16-bit extra field
3815  * is added to make the alignment clean; the field can be used by
3816  * heap objects when 16-bit packing is used. This field is now
3817  * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
3818  * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
3819  * this only matter to low memory environments anyway.
3820  */
3821 #if defined(DUK_USE_HEAPPTR16)
3822  duk_uint16_t h_extra16;
3823 #endif
3824 };
3825 
3827  /* 16 bits would be enough for shared heaphdr flags and duk_hstring
3828  * flags. The initial parts of duk_heaphdr_string and duk_heaphdr
3829  * must match so changing the flags field size here would be quite
3830  * awkward. However, to minimize struct size, we can pack at least
3831  * 16 bits of duk_hstring data into the flags field.
3832  */
3833  duk_uint32_t h_flags;
3834 
3835 #if defined(DUK_USE_REFERENCE_COUNTING)
3836 #if defined(DUK_USE_REFCOUNT16)
3837  duk_uint16_t h_refcount16;
3838  duk_uint16_t h_strextra16; /* round out to 8 bytes */
3839 #else
3840  duk_size_t h_refcount;
3841 #endif
3842 #else
3843  duk_uint16_t h_strextra16;
3844 #endif
3845 };
3846 
3847 #define DUK_HEAPHDR_FLAGS_TYPE_MASK 0x00000003UL
3848 #define DUK_HEAPHDR_FLAGS_FLAG_MASK (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
3849 
3850  /* 2 bits for heap type */
3851 #define DUK_HEAPHDR_FLAGS_HEAP_START 2 /* 5 heap flags */
3852 #define DUK_HEAPHDR_FLAGS_USER_START 7 /* 25 user flags */
3853 
3854 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
3855 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n) (DUK_HEAPHDR_FLAGS_USER_START + (n))
3856 #define DUK_HEAPHDR_HEAP_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
3857 #define DUK_HEAPHDR_USER_FLAG(n) (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
3858 
3859 #define DUK_HEAPHDR_FLAG_REACHABLE DUK_HEAPHDR_HEAP_FLAG(0) /* mark-and-sweep: reachable */
3860 #define DUK_HEAPHDR_FLAG_TEMPROOT DUK_HEAPHDR_HEAP_FLAG(1) /* mark-and-sweep: children not processed */
3861 #define DUK_HEAPHDR_FLAG_FINALIZABLE DUK_HEAPHDR_HEAP_FLAG(2) /* mark-and-sweep: finalizable (on current pass) */
3862 #define DUK_HEAPHDR_FLAG_FINALIZED DUK_HEAPHDR_HEAP_FLAG(3) /* mark-and-sweep: finalized (on previous pass) */
3863 #define DUK_HEAPHDR_FLAG_READONLY DUK_HEAPHDR_HEAP_FLAG(4) /* read-only object, in code section */
3864 
3865 #define DUK_HTYPE_MIN 0
3866 #define DUK_HTYPE_STRING 0
3867 #define DUK_HTYPE_OBJECT 1
3868 #define DUK_HTYPE_BUFFER 2
3869 #define DUK_HTYPE_MAX 2
3870 
3871 #if defined(DUK_USE_HEAPPTR16)
3872 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
3873  ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
3874 #define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3875  (h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
3876  } while (0)
3877 #else
3878 #define DUK_HEAPHDR_GET_NEXT(heap,h) ((h)->h_next)
3879 #define DUK_HEAPHDR_SET_NEXT(heap,h,val) do { \
3880  (h)->h_next = (val); \
3881  } while (0)
3882 #endif
3883 
3884 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3885 #if defined(DUK_USE_HEAPPTR16)
3886 #define DUK_HEAPHDR_GET_PREV(heap,h) \
3887  ((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
3888 #define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3889  (h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
3890  } while (0)
3891 #else
3892 #define DUK_HEAPHDR_GET_PREV(heap,h) ((h)->h_prev)
3893 #define DUK_HEAPHDR_SET_PREV(heap,h,val) do { \
3894  (h)->h_prev = (val); \
3895  } while (0)
3896 #endif
3897 #endif
3898 
3899 #if defined(DUK_USE_REFERENCE_COUNTING)
3900 #if defined(DUK_USE_REFCOUNT16)
3901 #define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount16)
3902 #define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3903  (h)->h_refcount16 = (val); \
3904  } while (0)
3905 #define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount16) /* result: updated refcount */
3906 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount16) /* result: updated refcount */
3907 #else
3908 #define DUK_HEAPHDR_GET_REFCOUNT(h) ((h)->h_refcount)
3909 #define DUK_HEAPHDR_SET_REFCOUNT(h,val) do { \
3910  (h)->h_refcount = (val); \
3911  } while (0)
3912 #define DUK_HEAPHDR_PREINC_REFCOUNT(h) (++(h)->h_refcount) /* result: updated refcount */
3913 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h) (--(h)->h_refcount) /* result: updated refcount */
3914 #endif
3915 #else
3916 /* refcount macros not defined without refcounting, caller must #if defined() now */
3917 #endif /* DUK_USE_REFERENCE_COUNTING */
3918 
3919 /*
3920  * Note: type is treated as a field separate from flags, so some masking is
3921  * involved in the macros below.
3922  */
3923 
3924 #define DUK_HEAPHDR_GET_FLAGS_RAW(h) ((h)->h_flags)
3925 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val) do { \
3926  (h)->h_flags = (val); } \
3927  }
3928 #define DUK_HEAPHDR_GET_FLAGS(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
3929 #define DUK_HEAPHDR_SET_FLAGS(h,val) do { \
3930  (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
3931  } while (0)
3932 #define DUK_HEAPHDR_GET_TYPE(h) ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
3933 #define DUK_HEAPHDR_SET_TYPE(h,val) do { \
3934  (h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
3935  } while (0)
3936 
3937 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
3938  * and the comparison is unsigned, it's always true and generates warnings.
3939  */
3940 #define DUK_HEAPHDR_HTYPE_VALID(h) ( \
3941  DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
3942  )
3943 
3944 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval) do { \
3945  (h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
3946  ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
3947  } while (0)
3948 
3949 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits) do { \
3950  DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3951  (h)->h_flags |= (bits); \
3952  } while (0)
3953 
3954 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits) do { \
3955  DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
3956  (h)->h_flags &= ~((bits)); \
3957  } while (0)
3958 
3959 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits) (((h)->h_flags & (bits)) != 0)
3960 
3961 #define DUK_HEAPHDR_SET_REACHABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3962 #define DUK_HEAPHDR_CLEAR_REACHABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3963 #define DUK_HEAPHDR_HAS_REACHABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
3964 
3965 #define DUK_HEAPHDR_SET_TEMPROOT(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3966 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3967 #define DUK_HEAPHDR_HAS_TEMPROOT(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
3968 
3969 #define DUK_HEAPHDR_SET_FINALIZABLE(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3970 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3971 #define DUK_HEAPHDR_HAS_FINALIZABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
3972 
3973 #define DUK_HEAPHDR_SET_FINALIZED(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3974 #define DUK_HEAPHDR_CLEAR_FINALIZED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3975 #define DUK_HEAPHDR_HAS_FINALIZED(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
3976 
3977 #define DUK_HEAPHDR_SET_READONLY(h) DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3978 #define DUK_HEAPHDR_CLEAR_READONLY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3979 #define DUK_HEAPHDR_HAS_READONLY(h) DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
3980 
3981 /* get or set a range of flags; m=first bit number, n=number of bits */
3982 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n) (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
3983 
3984 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v) do { \
3985  (h)->h_flags = \
3986  ((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
3987  | ((v) << (m)); \
3988  } while (0)
3989 
3990 /* init pointer fields to null */
3991 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
3992 #define DUK_HEAPHDR_INIT_NULLS(h) do { \
3993  DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3994  DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
3995  } while (0)
3996 #else
3997 #define DUK_HEAPHDR_INIT_NULLS(h) do { \
3998  DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
3999  } while (0)
4000 #endif
4001 
4002 #define DUK_HEAPHDR_STRING_INIT_NULLS(h) /* currently nop */
4003 
4004 /*
4005  * Type tests
4006  */
4007 
4008 #define DUK_HEAPHDR_IS_OBJECT(h) \
4009  (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4010 #define DUK_HEAPHDR_IS_STRING(h) \
4011  (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4012 #define DUK_HEAPHDR_IS_BUFFER(h) \
4013  (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4014 
4015 /*
4016  * Assert helpers
4017  */
4018 
4019 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4020  * h->prev->next should point back to h.
4021  */
4022 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
4023 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
4024  if ((h) != NULL) { \
4025  duk_heaphdr *h__prev, *h__next; \
4026  h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
4027  h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
4028  DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
4029  DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
4030  } \
4031  } while (0)
4032 #else
4033 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
4034 #endif
4035 
4036 /*
4037  * Reference counting helper macros. The macros take a thread argument
4038  * and must thus always be executed in a specific thread context. The
4039  * thread argument is needed for features like finalization. Currently
4040  * it is not required for INCREF, but it is included just in case.
4041  *
4042  * Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4043  * defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4044  * around them.
4045  */
4046 
4047 #if defined(DUK_USE_REFERENCE_COUNTING)
4048 
4049 #if defined(DUK_USE_ROM_OBJECTS)
4050 /* With ROM objects "needs refcount update" is true when the value is
4051  * heap allocated and is not a ROM object.
4052  */
4053 /* XXX: double evaluation for 'tv' argument. */
4054 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4055  (DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4056 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) (!DUK_HEAPHDR_HAS_READONLY((h)))
4057 #else /* DUK_USE_ROM_OBJECTS */
4058 /* Without ROM objects "needs refcount update" == is heap allocated. */
4059 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4060 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 1
4061 #endif /* DUK_USE_ROM_OBJECTS */
4062 
4063 /* Fast variants, inline refcount operations except for refzero handling.
4064  * Can be used explicitly when speed is always more important than size.
4065  * For a good compiler and a single file build, these are basically the
4066  * same as a forced inline.
4067  */
4068 #define DUK_TVAL_INCREF_FAST(thr,tv) do { \
4069  duk_tval *duk__tv = (tv); \
4070  DUK_ASSERT(duk__tv != NULL); \
4071  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4072  duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4073  DUK_ASSERT(duk__h != NULL); \
4074  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4075  DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4076  } \
4077  } while (0)
4078 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4079  duk_tval *duk__tv = (tv); \
4080  DUK_ASSERT(duk__tv != NULL); \
4081  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4082  duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4083  DUK_ASSERT(duk__h != NULL); \
4084  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4085  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4086  if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4087  duk_heaphdr_refzero((thr), duk__h); \
4088  } \
4089  } \
4090  } while (0)
4091 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4092  duk_tval *duk__tv = (tv); \
4093  DUK_ASSERT(duk__tv != NULL); \
4094  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4095  duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4096  DUK_ASSERT(duk__h != NULL); \
4097  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4098  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4099  if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4100  duk_heaphdr_refzero_norz((thr), duk__h); \
4101  } \
4102  } \
4103  } while (0)
4104 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4105  duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4106  DUK_ASSERT(duk__h != NULL); \
4107  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4108  if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4109  DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4110  } \
4111  } while (0)
4112 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4113  duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4114  DUK_ASSERT(duk__h != NULL); \
4115  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4116  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4117  if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4118  if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4119  (rzcall)((thr), (rzcast) duk__h); \
4120  } \
4121  } \
4122  } while (0)
4123 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4124  DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4125 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4126  DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4127 
4128 /* Slow variants, call to a helper to reduce code size.
4129  * Can be used explicitly when size is always more important than speed.
4130  */
4131 #define DUK_TVAL_INCREF_SLOW(thr,tv) do { duk_tval_incref((tv)); } while (0)
4132 #define DUK_TVAL_DECREF_SLOW(thr,tv) do { duk_tval_decref((thr), (tv)); } while (0)
4133 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv) do { duk_tval_decref_norz((thr), (tv)); } while (0)
4134 #define DUK_HEAPHDR_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4135 #define DUK_HEAPHDR_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4136 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4137 #define DUK_HSTRING_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4138 #define DUK_HSTRING_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4139 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4140 #define DUK_HBUFFER_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4141 #define DUK_HBUFFER_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4142 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4143 #define DUK_HOBJECT_INCREF_SLOW(thr,h) do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4144 #define DUK_HOBJECT_DECREF_SLOW(thr,h) do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4145 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4146 
4147 /* Default variants. Selection depends on speed/size preference.
4148  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4149  * is about +1kB for _FAST variants.
4150  */
4151 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4152 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4153  * but current refzero queue handling prevents that.
4154  */
4155 #define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_FAST((thr),(tv))
4156 #define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_FAST((thr),(tv))
4157 #define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4158 #define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_FAST((thr),(h))
4159 #define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4160 #define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4161 #define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4162 #define DUK_HSTRING_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4163 #define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *) /* no 'norz' variant */
4164 #define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4165 #define DUK_HOBJECT_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4166 #define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4167 #define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4168 #define DUK_HBUFFER_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4169 #define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *) /* no 'norz' variant */
4170 #define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4171 #define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4172 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4173 #define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4174 #define DUK_HNATFUNC_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4175 #define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4176 #define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4177 #define DUK_HBUFOBJ_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4178 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4179 #define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4180 #define DUK_HTHREAD_DECREF(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4181 #define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4182 #else
4183 #define DUK_TVAL_INCREF(thr,tv) DUK_TVAL_INCREF_SLOW((thr),(tv))
4184 #define DUK_TVAL_DECREF(thr,tv) DUK_TVAL_DECREF_SLOW((thr),(tv))
4185 #define DUK_TVAL_DECREF_NORZ(thr,tv) DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4186 #define DUK_HEAPHDR_INCREF(thr,h) DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4187 #define DUK_HEAPHDR_DECREF(thr,h) DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4188 #define DUK_HEAPHDR_DECREF_NORZ(thr,h) DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4189 #define DUK_HSTRING_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4190 #define DUK_HSTRING_DECREF(thr,h) DUK_HSTRING_DECREF_SLOW((thr),(h))
4191 #define DUK_HSTRING_DECREF_NORZ(thr,h) DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4192 #define DUK_HOBJECT_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4193 #define DUK_HOBJECT_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(h))
4194 #define DUK_HOBJECT_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4195 #define DUK_HBUFFER_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4196 #define DUK_HBUFFER_DECREF(thr,h) DUK_HBUFFER_DECREF_SLOW((thr),(h))
4197 #define DUK_HBUFFER_DECREF_NORZ(thr,h) DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4198 #define DUK_HCOMPFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4199 #define DUK_HCOMPFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4200 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4201 #define DUK_HNATFUNC_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4202 #define DUK_HNATFUNC_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4203 #define DUK_HNATFUNC_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4204 #define DUK_HBUFOBJ_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4205 #define DUK_HBUFOBJ_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4206 #define DUK_HBUFOB_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4207 #define DUK_HTHREAD_INCREF(thr,h) DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4208 #define DUK_HTHREAD_DECREF(thr,h) DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4209 #define DUK_HTHREAD_DECREF_NORZ(thr,h) DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4210 #endif
4211 
4212 /* Convenience for some situations; the above macros don't allow NULLs
4213  * for performance reasons. Macros cover only actually needed cases.
4214  */
4215 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4216  if ((h) != NULL) { \
4217  DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4218  } \
4219  } while (0)
4220 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4221  if ((h) != NULL) { \
4222  DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4223  } \
4224  } while (0)
4225 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4226  if ((h) != NULL) { \
4227  DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4228  } \
4229  } while (0)
4230 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4231  if ((h) != NULL) { \
4232  DUK_HOBJECT_INCREF((thr), (h)); \
4233  } \
4234  } while (0)
4235 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4236  if ((h) != NULL) { \
4237  DUK_HOBJECT_DECREF((thr), (h)); \
4238  } \
4239  } while (0)
4240 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4241  if ((h) != NULL) { \
4242  DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4243  } \
4244  } while (0)
4245 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4246  if ((h) != NULL) { \
4247  DUK_HBUFFER_INCREF((thr), (h)); \
4248  } \
4249  } while (0)
4250 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4251  if ((h) != NULL) { \
4252  DUK_HBUFFER_DECREF((thr), (h)); \
4253  } \
4254  } while (0)
4255 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4256  if ((h) != NULL) { \
4257  DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4258  } \
4259  } while (0)
4260 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
4261  if ((h) != NULL) { \
4262  DUK_HTHREAD_INCREF((thr), (h)); \
4263  } \
4264  } while (0)
4265 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
4266  if ((h) != NULL) { \
4267  DUK_HTHREAD_DECREF((thr), (h)); \
4268  } \
4269  } while (0)
4270 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4271  if ((h) != NULL) { \
4272  DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
4273  } \
4274  } while (0)
4275 
4276 /* Free pending refzero entries; quick check to avoid call because often
4277  * the queue is empty.
4278  */
4279 #define DUK_REFZERO_CHECK_FAST(thr) do { \
4280  if ((thr)->heap->refzero_list != NULL) { \
4281  duk_refzero_free_pending((thr)); \
4282  } \
4283  } while (0)
4284 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
4285  duk_refzero_free_pending((thr)); \
4286  } while (0)
4287 
4288 /*
4289  * Macros to set a duk_tval and update refcount of the target (decref the
4290  * old value and incref the new value if necessary). This is both performance
4291  * and footprint critical; any changes made should be measured for size/speed.
4292  */
4293 
4294 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4295  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4296  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4297  DUK_TVAL_SET_UNDEFINED(tv__dst); \
4298  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4299  } while (0)
4300 
4301 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
4302  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4303  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4304  DUK_TVAL_SET_UNDEFINED(tv__dst); \
4305  DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
4306  } while (0)
4307 
4308 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4309  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4310  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4311  DUK_TVAL_SET_UNUSED(tv__dst); \
4312  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4313  } while (0)
4314 
4315 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4316  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4317  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4318  DUK_TVAL_SET_NULL(tv__dst); \
4319  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4320  } while (0)
4321 
4322 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4323  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4324  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4325  DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4326  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4327  } while (0)
4328 
4329 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4330  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4331  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4332  DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4333  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4334  } while (0)
4335 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4336  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4337  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4338  DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
4339  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4340  } while (0)
4341 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4342  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4343  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4344  DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4345  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4346  } while (0)
4347 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
4348  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4349  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4350  DUK_TVAL_SET_NAN(tv__dst); \
4351  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4352  } while (0)
4353 #if defined(DUK_USE_FASTINT)
4354 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4355  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4356  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4357  DUK_TVAL_SET_I48(tv__dst, (newval)); \
4358  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4359  } while (0)
4360 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4361  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4362  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4363  DUK_TVAL_SET_I32(tv__dst, (newval)); \
4364  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4365  } while (0)
4366 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4367  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4368  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4369  DUK_TVAL_SET_U32(tv__dst, (newval)); \
4370  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4371  } while (0)
4372 #else
4373 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
4374  DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
4375 #endif /* DUK_USE_FASTINT */
4376 
4377 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
4378  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4379  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4380  DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
4381  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4382  } while (0)
4383 
4384 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4385  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4386  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4387  DUK_TVAL_SET_STRING(tv__dst, (newval)); \
4388  DUK_HSTRING_INCREF((thr), (newval)); \
4389  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4390  } while (0)
4391 
4392 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4393  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4394  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4395  DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
4396  DUK_HOBJECT_INCREF((thr), (newval)); \
4397  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4398  } while (0)
4399 
4400 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4401  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4402  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4403  DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
4404  DUK_HBUFFER_INCREF((thr), (newval)); \
4405  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4406  } while (0)
4407 
4408 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4409  duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4410  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4411  DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
4412  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4413  } while (0)
4414 
4415 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
4416  * etc, so it's very important for performance. Measure when changing.
4417  *
4418  * NOTE: the source and destination duk_tval pointers may be the same, and
4419  * the macros MUST deal with that correctly.
4420  */
4421 
4422 /* Original idiom used, minimal code size. */
4423 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
4424  duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
4425  tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4426  DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4427  DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4428  DUK_TVAL_INCREF((thr), tv__src); \
4429  DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
4430  } while (0)
4431 
4432 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
4433  * fast incref/decref macros.
4434  */
4435 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
4436  duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
4437  tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4438  DUK_TVAL_INCREF_FAST((thr), tv__src); \
4439  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
4440  h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
4441  DUK_ASSERT(h__obj != NULL); \
4442  DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4443  DUK_HEAPHDR_DECREF_FAST((thr), h__obj); /* side effects */ \
4444  } else { \
4445  DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4446  } \
4447  } while (0)
4448 
4449 /* XXX: no optimized variants yet */
4450 #define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4451 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
4452 #define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4453 #define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4454 #define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4455 #define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4456 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4457 #define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4458 #define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4459 #if defined(DUK_USE_FASTINT)
4460 #define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
4461 #define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
4462 #define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
4463 #else
4464 #define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast int-to-double */
4465 #define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4466 #define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4467 #endif /* DUK_USE_FASTINT */
4468 #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
4469 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4470 #define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4471 #define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4472 #define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4473 #define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4474 
4475 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4476 /* Optimized for speed. */
4477 #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT1
4478 #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT1
4479 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4480 #else
4481 /* Optimized for size. */
4482 #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4483 #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4484 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4485 #endif
4486 
4487 #else /* DUK_USE_REFERENCE_COUNTING */
4488 
4489 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) 0
4490 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h) 0
4491 
4492 #define DUK_TVAL_INCREF_FAST(thr,v) do {} while (0) /* nop */
4493 #define DUK_TVAL_DECREF_FAST(thr,v) do {} while (0) /* nop */
4494 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v) do {} while (0) /* nop */
4495 #define DUK_TVAL_INCREF_SLOW(thr,v) do {} while (0) /* nop */
4496 #define DUK_TVAL_DECREF_SLOW(thr,v) do {} while (0) /* nop */
4497 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v) do {} while (0) /* nop */
4498 #define DUK_TVAL_INCREF(thr,v) do {} while (0) /* nop */
4499 #define DUK_TVAL_DECREF(thr,v) do {} while (0) /* nop */
4500 #define DUK_TVAL_DECREF_NORZ(thr,v) do {} while (0) /* nop */
4501 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do {} while (0) /* nop */
4502 #define DUK_HEAPHDR_DECREF_FAST(thr,h) do {} while (0) /* nop */
4503 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
4504 #define DUK_HEAPHDR_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4505 #define DUK_HEAPHDR_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4506 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
4507 #define DUK_HEAPHDR_INCREF(thr,h) do {} while (0) /* nop */
4508 #define DUK_HEAPHDR_DECREF(thr,h) do {} while (0) /* nop */
4509 #define DUK_HEAPHDR_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4510 #define DUK_HSTRING_INCREF_FAST(thr,h) do {} while (0) /* nop */
4511 #define DUK_HSTRING_DECREF_FAST(thr,h) do {} while (0) /* nop */
4512 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
4513 #define DUK_HSTRING_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4514 #define DUK_HSTRING_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4515 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
4516 #define DUK_HSTRING_INCREF(thr,h) do {} while (0) /* nop */
4517 #define DUK_HSTRING_DECREF(thr,h) do {} while (0) /* nop */
4518 #define DUK_HSTRING_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4519 #define DUK_HOBJECT_INCREF_FAST(thr,h) do {} while (0) /* nop */
4520 #define DUK_HOBJECT_DECREF_FAST(thr,h) do {} while (0) /* nop */
4521 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
4522 #define DUK_HOBJECT_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4523 #define DUK_HOBJECT_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4524 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
4525 #define DUK_HOBJECT_INCREF(thr,h) do {} while (0) /* nop */
4526 #define DUK_HOBJECT_DECREF(thr,h) do {} while (0) /* nop */
4527 #define DUK_HOBJECT_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4528 #define DUK_HBUFFER_INCREF_FAST(thr,h) do {} while (0) /* nop */
4529 #define DUK_HBUFFER_DECREF_FAST(thr,h) do {} while (0) /* nop */
4530 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h) do {} while (0) /* nop */
4531 #define DUK_HBUFFER_INCREF_SLOW(thr,h) do {} while (0) /* nop */
4532 #define DUK_HBUFFER_DECREF_SLOW(thr,h) do {} while (0) /* nop */
4533 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h) do {} while (0) /* nop */
4534 #define DUK_HBUFFER_INCREF(thr,h) do {} while (0) /* nop */
4535 #define DUK_HBUFFER_DECREF(thr,h) do {} while (0) /* nop */
4536 #define DUK_HBUFFER_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4537 
4538 #define DUK_HCOMPFUNC_INCREF(thr,h) do {} while (0) /* nop */
4539 #define DUK_HCOMPFUNC_DECREF(thr,h) do {} while (0) /* nop */
4540 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4541 #define DUK_HNATFUNC_INCREF(thr,h) do {} while (0) /* nop */
4542 #define DUK_HNATFUNC_DECREF(thr,h) do {} while (0) /* nop */
4543 #define DUK_HNATFUNC_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4544 #define DUK_HBUFOBJ_INCREF(thr,h) do {} while (0) /* nop */
4545 #define DUK_HBUFOBJ_DECREF(thr,h) do {} while (0) /* nop */
4546 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4547 #define DUK_HTHREAD_INCREF(thr,h) do {} while (0) /* nop */
4548 #define DUK_HTHREAD_DECREF(thr,h) do {} while (0) /* nop */
4549 #define DUK_HTHREAD_DECREF_NORZ(thr,h) do {} while (0) /* nop */
4550 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4551 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4552 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */
4553 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4554 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do {} while (0) /* nop */
4555 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do {} while (0) /* nop */
4556 
4557 #define DUK_REFZERO_CHECK_FAST(thr) do {} while (0) /* nop */
4558 #define DUK_REFZERO_CHECK_SLOW(thr) do {} while (0) /* nop */
4559 
4560 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4561  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4562  DUK_TVAL_SET_UNDEFINED(tv__dst); \
4563  DUK_UNREF((thr)); \
4564  } while (0)
4565 
4566 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4567  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4568  DUK_TVAL_SET_UNUSED(tv__dst); \
4569  DUK_UNREF((thr)); \
4570  } while (0)
4571 
4572 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4573  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4574  DUK_TVAL_SET_NULL(tv__dst); \
4575  DUK_UNREF((thr)); \
4576  } while (0)
4577 
4578 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4579  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4580  DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4581  DUK_UNREF((thr)); \
4582  } while (0)
4583 
4584 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4585  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4586  DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4587  DUK_UNREF((thr)); \
4588  } while (0)
4589 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4590  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4591  DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
4592  DUK_UNREF((thr)); \
4593  } while (0)
4594 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4595  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4596  DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
4597  DUK_UNREF((thr)); \
4598  } while (0)
4599 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
4600  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4601  DUK_TVAL_SET_NAN(tv__dst); \
4602  DUK_UNREF((thr)); \
4603  } while (0)
4604 #if defined(DUK_USE_FASTINT)
4605 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4606  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4607  DUK_TVAL_SET_I48(tv__dst, (newval)); \
4608  DUK_UNREF((thr)); \
4609  } while (0)
4610 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4611  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4612  DUK_TVAL_SET_I32(tv__dst, (newval)); \
4613  DUK_UNREF((thr)); \
4614  } while (0)
4615 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4616  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4617  DUK_TVAL_SET_U32(tv__dst, (newval)); \
4618  DUK_UNREF((thr)); \
4619  } while (0)
4620 #else
4621 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
4622  DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
4623 #endif /* DUK_USE_FASTINT */
4624 
4625 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
4626  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4627  DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
4628  DUK_UNREF((thr)); \
4629  } while (0)
4630 
4631 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4632  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4633  DUK_TVAL_SET_STRING(tv__dst, (newval)); \
4634  DUK_UNREF((thr)); \
4635  } while (0)
4636 
4637 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4638  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4639  DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
4640  DUK_UNREF((thr)); \
4641  } while (0)
4642 
4643 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4644  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4645  DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
4646  DUK_UNREF((thr)); \
4647  } while (0)
4648 
4649 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4650  duk_tval *tv__dst; tv__dst = (tvptr_dst); \
4651  DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
4652  DUK_UNREF((thr)); \
4653  } while (0)
4654 
4655 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
4656  duk_tval *tv__dst, *tv__src; \
4657  tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
4658  DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
4659  DUK_UNREF((thr)); \
4660  } while (0)
4661 
4662 #define DUK_TVAL_SET_UNDEFINED_UPDREF DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4663 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
4664 #define DUK_TVAL_SET_UNUSED_UPDREF DUK_TVAL_SET_UNUSED_UPDREF_ALT0
4665 #define DUK_TVAL_SET_NULL_UPDREF DUK_TVAL_SET_NULL_UPDREF_ALT0
4666 #define DUK_TVAL_SET_BOOLEAN_UPDREF DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
4667 #define DUK_TVAL_SET_NUMBER_UPDREF DUK_TVAL_SET_NUMBER_UPDREF_ALT0
4668 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
4669 #define DUK_TVAL_SET_DOUBLE_UPDREF DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
4670 #define DUK_TVAL_SET_NAN_UPDREF DUK_TVAL_SET_NAN_UPDREF_ALT0
4671 #if defined(DUK_USE_FASTINT)
4672 #define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_I48_UPDREF_ALT0
4673 #define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_I32_UPDREF_ALT0
4674 #define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_U32_UPDREF_ALT0
4675 #else
4676 #define DUK_TVAL_SET_I48_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF /* XXX: fast-int-to-double */
4677 #define DUK_TVAL_SET_I32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4678 #define DUK_TVAL_SET_U32_UPDREF DUK_TVAL_SET_DOUBLE_CAST_UPDREF
4679 #endif /* DUK_USE_FASTINT */
4680 #define DUK_TVAL_SET_FASTINT_UPDREF DUK_TVAL_SET_I48_UPDREF /* convenience */
4681 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
4682 #define DUK_TVAL_SET_STRING_UPDREF DUK_TVAL_SET_STRING_UPDREF_ALT0
4683 #define DUK_TVAL_SET_OBJECT_UPDREF DUK_TVAL_SET_OBJECT_UPDREF_ALT0
4684 #define DUK_TVAL_SET_BUFFER_UPDREF DUK_TVAL_SET_BUFFER_UPDREF_ALT0
4685 #define DUK_TVAL_SET_POINTER_UPDREF DUK_TVAL_SET_POINTER_UPDREF_ALT0
4686 
4687 #define DUK_TVAL_SET_TVAL_UPDREF DUK_TVAL_SET_TVAL_UPDREF_ALT0
4688 #define DUK_TVAL_SET_TVAL_UPDREF_FAST DUK_TVAL_SET_TVAL_UPDREF_ALT0
4689 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW DUK_TVAL_SET_TVAL_UPDREF_ALT0
4690 
4691 #endif /* DUK_USE_REFERENCE_COUNTING */
4692 
4693 #endif /* DUK_HEAPHDR_H_INCLUDED */
4694 /* #include duk_api_internal.h */
4695 /*
4696  * Internal API calls which have (stack and other) semantics similar
4697  * to the public API.
4698  */
4699 
4700 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
4701 #define DUK_API_INTERNAL_H_INCLUDED
4702 
4703 /* duk_push_sprintf constants */
4704 #define DUK_PUSH_SPRINTF_INITIAL_SIZE 256L
4705 #define DUK_PUSH_SPRINTF_SANITY_LIMIT (1L * 1024L * 1024L * 1024L)
4706 
4707 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
4708  * blamed as source of error for error fileName / lineNumber.
4709  */
4710 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE (1L << 24)
4711 
4712 /* Valstack resize flags */
4713 #define DUK_VSRESIZE_FLAG_SHRINK (1 << 0)
4714 #define DUK_VSRESIZE_FLAG_COMPACT (1 << 1)
4715 #define DUK_VSRESIZE_FLAG_THROW (1 << 2)
4716 
4717 /* Current convention is to use duk_size_t for value stack sizes and global indices,
4718  * and duk_idx_t for local frame indices.
4719  */
4720 DUK_INTERNAL_DECL
4721 duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
4722  duk_size_t min_new_size,
4723  duk_small_uint_t flags);
4724 
4725 DUK_INTERNAL_DECL void duk_dup_0(duk_context *ctx);
4726 DUK_INTERNAL_DECL void duk_dup_1(duk_context *ctx);
4727 DUK_INTERNAL_DECL void duk_dup_2(duk_context *ctx);
4728 /* duk_dup_m1() would be same as duk_dup_top() */
4729 DUK_INTERNAL_DECL void duk_dup_m2(duk_context *ctx);
4730 DUK_INTERNAL_DECL void duk_dup_m3(duk_context *ctx);
4731 DUK_INTERNAL_DECL void duk_dup_m4(duk_context *ctx);
4732 
4733 DUK_INTERNAL_DECL void duk_remove_m2(duk_context *ctx);
4734 
4735 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
4736 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
4737 
4738 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
4739 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_context *ctx, duk_idx_t idx);
4740 #endif
4741 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_context *ctx, duk_idx_t idx);
4742 
4743 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t idx);
4744 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_context *ctx, duk_idx_t idx);
4745 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t idx);
4746 DUK_INTERNAL_DECL void duk_push_tval(duk_context *ctx, duk_tval *tv);
4747 
4748 /* Push the current 'this' binding; throw TypeError if binding is not object
4749  * coercible (CheckObjectCoercible).
4750  */
4751 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_context *ctx);
4752 
4753 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
4754 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx);
4755 
4756 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
4757 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx);
4758 
4759 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_context *ctx, duk_uint_t i);
4760 
4761 /* Get a borrowed duk_tval pointer to the current 'this' binding. Caller must
4762  * make sure there's an active callstack entry. Note that the returned pointer
4763  * is unstable with regards to side effects.
4764  */
4765 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx);
4766 
4767 /* XXX: add fastint support? */
4768 #define duk_push_u64(ctx,val) \
4769  duk_push_number((ctx), (duk_double_t) (val))
4770 #define duk_push_i64(ctx,val) \
4771  duk_push_number((ctx), (duk_double_t) (val))
4772 
4773 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
4774 #define duk_push_u32(ctx,val) \
4775  duk_push_uint((ctx), (duk_uint_t) (val))
4776 #define duk_push_i32(ctx,val) \
4777  duk_push_int((ctx), (duk_int_t) (val))
4778 
4779 /* sometimes stack and array indices need to go on the stack */
4780 #define duk_push_idx(ctx,val) \
4781  duk_push_int((ctx), (duk_int_t) (val))
4782 #define duk_push_uarridx(ctx,val) \
4783  duk_push_uint((ctx), (duk_uint_t) (val))
4784 #define duk_push_size_t(ctx,val) \
4785  duk_push_uint((ctx), (duk_uint_t) (val)) /* XXX: assumed to fit for now */
4786 
4787 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_context *ctx, duk_idx_t idx);
4788 
4789 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t idx);
4790 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_context *ctx, duk_idx_t idx);
4791 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_context *ctx, duk_idx_t idx);
4792 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t idx);
4793 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t idx);
4794 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t idx);
4795 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_context *ctx, duk_idx_t idx);
4796 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_context *ctx, duk_idx_t idx);
4797 
4798 DUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_bool_t throw_flag, duk_bool_t *out_found);
4799 
4800 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t idx, duk_small_uint_t classnum);
4801 
4802 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask);
4803 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask);
4804 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask);
4805 #define duk_require_hobject_promote_lfunc(ctx,idx) \
4806  duk_require_hobject_promote_mask((ctx), (idx), DUK_TYPE_MASK_LIGHTFUNC)
4807 #define duk_get_hobject_promote_lfunc(ctx,idx) \
4808  duk_get_hobject_promote_mask((ctx), (idx), DUK_TYPE_MASK_LIGHTFUNC)
4809 
4810 #if 0 /*unused*/
4811 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_context *ctx, duk_idx_t idx);
4812 #endif
4813 
4814 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_context *ctx, duk_idx_t idx);
4815 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_context *ctx, duk_idx_t idx);
4816 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_context *ctx, duk_idx_t idx);
4817 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_context *ctx, duk_idx_t idx);
4818 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_context *ctx, duk_idx_t idx);
4819 
4820 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_context *ctx, duk_tval *tv);
4821 
4822 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t idx);
4823 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_context *ctx);
4824 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_context *ctx, duk_idx_t idx);
4825 
4826 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_context *ctx, duk_idx_t idx);
4827 
4828 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_context *ctx);
4829 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_context *ctx);
4830 
4831 #if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
4832 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t idx);
4833 #endif
4834 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_context *ctx, duk_tval *tv);
4835 
4836 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped); /* out_clamped=NULL, RangeError if outside range */
4837 DUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
4838 DUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);
4839 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
4840 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t idx);
4841 #endif
4842 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_context *ctx, duk_idx_t idx);
4843 
4844 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t idx);
4845 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_context *ctx, duk_idx_t idx);
4846 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);
4847 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_context *ctx, duk_idx_t idx);
4848 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t idx);
4849 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t idx);
4850 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t idx);
4851 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_context *ctx, duk_idx_t idx);
4852 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_context *ctx, duk_idx_t idx);
4853 
4854 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t idx, duk_small_uint_t classnum);
4855 
4856 DUK_INTERNAL_DECL void duk_push_hstring(duk_context *ctx, duk_hstring *h);
4857 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_uint_t stridx);
4858 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_context *ctx);
4859 DUK_INTERNAL_DECL void duk_push_hobject(duk_context *ctx, duk_hobject *h);
4860 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h);
4861 #define duk_push_hthread(ctx,h) \
4862  duk_push_hobject((ctx), (duk_hobject *) (h))
4863 #define duk_push_hnatfunc(ctx,h) \
4864  duk_push_hobject((ctx), (duk_hobject *) (h))
4865 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx);
4866 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
4867 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
4868 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_context *ctx);
4869 DUK_INTERNAL_DECL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
4870 DUK_INTERNAL_DECL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs);
4871 
4872 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
4873  * duk_push_hobject() etc which don't create a new value.
4874  */
4875 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_context *ctx);
4876 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_context *ctx, duk_uint32_t size);
4877 
4878 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz);
4879 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_context *ctx, duk_c_function func, duk_small_uint_t lf_flags);
4880 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv);
4881 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv);
4882 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
4883 DUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);
4884 #endif
4885 
4886 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_context *ctx, duk_size_t len);
4887 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_context *ctx, duk_size_t len);
4888 
4889 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t idx);
4890 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv);
4891 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_context *ctx, duk_tval *tv);
4892 
4893 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
4894  * enough to be packed into a single 32-bit integer argument. Argument limits
4895  * vary per call; typically 16 bits are assigned to the signed value stack index
4896  * and the stridx. In practice these work well for footprint with constant
4897  * arguments and such call sites are also easiest to verify to be correct.
4898  */
4899 
4900 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [val] */
4901 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args);
4902 #define duk_get_prop_stridx_short(ctx,obj_idx,stridx) \
4903  (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
4904  DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
4905  duk_get_prop_stridx_short_raw((ctx), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
4906 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop); /* [] -> [] */
4907 
4908 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [val] -> [] */
4909 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args);
4910 #define duk_put_prop_stridx_short(ctx,obj_idx,stridx) \
4911  (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
4912  DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
4913  duk_put_prop_stridx_short_raw((ctx), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
4914 
4915 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
4916 #if 0 /* Too few call sites to be useful. */
4917 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args);
4918 #define duk_del_prop_stridx_short(ctx,obj_idx,stridx) \
4919  (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
4920  DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
4921  duk_del_prop_stridx_short_raw((ctx), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
4922 #endif
4923 #define duk_del_prop_stridx_short(ctx,obj_idx,stridx) \
4924  duk_del_prop_stridx((ctx), (obj_idx), (stridx))
4925 
4926 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
4927 #if 0 /* Too few call sites to be useful. */
4928 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args);
4929 #define duk_has_prop_stridx_short(ctx,obj_idx,stridx) \
4930  (DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
4931  DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
4932  duk_has_prop_stridx_short_raw((ctx), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
4933 #endif
4934 #define duk_has_prop_stridx_short(ctx,obj_idx,stridx) \
4935  duk_has_prop_stridx((ctx), (obj_idx), (stridx))
4936 
4937 DUK_INTERNAL_DECL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t desc_flags); /* [key val] -> [] */
4938 
4939 DUK_INTERNAL_DECL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags); /* [val] -> [] */
4940 
4941 /* XXX: Because stridx and desc_flags have a limited range, this call could
4942  * always pack stridx and desc_flags into a single argument.
4943  */
4944 DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags); /* [val] -> [] */
4945 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args);
4946 #define duk_xdef_prop_stridx_short(ctx,obj_idx,stridx,desc_flags) \
4947  (DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
4948  DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
4949  DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
4950  duk_xdef_prop_stridx_short_raw((ctx), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
4951 
4952 #define duk_xdef_prop_wec(ctx,obj_idx) \
4953  duk_xdef_prop((ctx), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
4954 #define duk_xdef_prop_index_wec(ctx,obj_idx,arr_idx) \
4955  duk_xdef_prop_index((ctx), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
4956 #define duk_xdef_prop_stridx_wec(ctx,obj_idx,stridx) \
4957  duk_xdef_prop_stridx((ctx), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
4958 #define duk_xdef_prop_stridx_short_wec(ctx,obj_idx,stridx) \
4959  duk_xdef_prop_stridx_short((ctx), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
4960 
4961 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags); /* [] -> [] */
4962 
4963 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx); /* [] -> [] */
4964 
4965 DUK_INTERNAL_DECL void duk_pack(duk_context *ctx, duk_idx_t count);
4966 #if 0
4967 DUK_INTERNAL_DECL void duk_unpack(duk_context *ctx);
4968 #endif
4969 
4970 DUK_INTERNAL_DECL void duk_require_constructor_call(duk_context *ctx);
4971 DUK_INTERNAL_DECL void duk_require_constructable(duk_context *ctx, duk_idx_t idx);
4972 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_context *ctx, duk_hstring *h);
4973 
4974 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_context *ctx);
4975 
4976 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_context *ctx, duk_idx_t min_top);
4977 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_context *ctx);
4978 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_context *ctx);
4979 
4980 DUK_INTERNAL_DECL void duk_compact_m1(duk_context *ctx);
4981 
4982 /* Raw internal valstack access macros: access is unsafe so call site
4983  * must have a guarantee that the index is valid. When that is the case,
4984  * using these macro results in faster and smaller code than duk_get_tval().
4985  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
4986  */
4987 #define DUK_ASSERT_VALID_NEGIDX(ctx,idx) \
4988  (DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4989 #define DUK_ASSERT_VALID_POSIDX(ctx,idx) \
4990  (DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((ctx), (idx))))
4991 #define DUK_GET_TVAL_NEGIDX(ctx,idx) \
4992  (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_top + (idx))
4993 #define DUK_GET_TVAL_POSIDX(ctx,idx) \
4994  (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), ((duk_hthread *) (ctx))->valstack_bottom + (idx))
4995 #define DUK_GET_HOBJECT_NEGIDX(ctx,idx) \
4996  (DUK_ASSERT_VALID_NEGIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_top + (idx)))
4997 #define DUK_GET_HOBJECT_POSIDX(ctx,idx) \
4998  (DUK_ASSERT_VALID_POSIDX((ctx),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (ctx))->valstack_bottom + (idx)))
4999 
5000 #define DUK_GET_THIS_TVAL_PTR(thr) \
5001  (DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5002  (thr)->valstack_bottom - 1)
5003 
5004 #endif /* DUK_API_INTERNAL_H_INCLUDED */
5005 /* #include duk_hstring.h */
5006 /*
5007  * Heap string representation.
5008  *
5009  * Strings are byte sequences ordinarily stored in extended UTF-8 format,
5010  * allowing values larger than the official UTF-8 range (used internally)
5011  * and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5012  * Strings may also be invalid UTF-8 altogether which is the case e.g. with
5013  * strings used as internal property names and raw buffers converted to
5014  * strings. In such cases the 'clen' field contains an inaccurate value.
5015  *
5016  * Ecmascript requires support for 32-bit long strings. However, since each
5017  * 16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5018  * support about 1.4G codepoint long strings in extreme cases. This is not
5019  * really a practical issue.
5020  */
5021 
5022 #if !defined(DUK_HSTRING_H_INCLUDED)
5023 #define DUK_HSTRING_H_INCLUDED
5024 
5025 /* Impose a maximum string length for now. Restricted artificially to
5026  * ensure adding a heap header length won't overflow size_t. The limit
5027  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5028  *
5029  * E5.1 makes provisions to support strings longer than 4G characters.
5030  * This limit should be eliminated on 64-bit platforms (and increased
5031  * closer to maximum support on 32-bit platforms).
5032  */
5033 
5034 #if defined(DUK_USE_STRLEN16)
5035 #define DUK_HSTRING_MAX_BYTELEN (0x0000ffffUL)
5036 #else
5037 #define DUK_HSTRING_MAX_BYTELEN (0x7fffffffUL)
5038 #endif
5039 
5040 /* XXX: could add flags for "is valid CESU-8" (Ecmascript compatible strings),
5041  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5042  * regexp bytecode is), and "contains non-BMP characters". These are not
5043  * needed right now.
5044  */
5045 
5046 #define DUK_HSTRING_FLAG_ASCII DUK_HEAPHDR_USER_FLAG(0) /* string is ASCII, clen == blen */
5047 #define DUK_HSTRING_FLAG_ARRIDX DUK_HEAPHDR_USER_FLAG(1) /* string is a valid array index */
5048 #define DUK_HSTRING_FLAG_SYMBOL DUK_HEAPHDR_USER_FLAG(2) /* string is a symbol (invalid utf-8) */
5049 #define DUK_HSTRING_FLAG_HIDDEN DUK_HEAPHDR_USER_FLAG(3) /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5050 #define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(4) /* string is a reserved word (non-strict) */
5051 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(5) /* string is a reserved word (strict) */
5052 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(6) /* string is 'eval' or 'arguments' */
5053 #define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(7) /* string data is external (duk_hstring_external) */
5054 
5055 #define DUK_HSTRING_HAS_ASCII(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5056 #define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5057 #define DUK_HSTRING_HAS_SYMBOL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5058 #define DUK_HSTRING_HAS_HIDDEN(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5059 #define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5060 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5061 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5062 #define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5063 
5064 #define DUK_HSTRING_SET_ASCII(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5065 #define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5066 #define DUK_HSTRING_SET_SYMBOL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5067 #define DUK_HSTRING_SET_HIDDEN(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5068 #define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5069 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5070 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5071 #define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5072 
5073 #define DUK_HSTRING_CLEAR_ASCII(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5074 #define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5075 #define DUK_HSTRING_CLEAR_SYMBOL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5076 #define DUK_HSTRING_CLEAR_HIDDEN(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5077 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5078 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5079 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5080 #define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5081 
5082 #if 0 /* Slightly smaller code without explicit flag, but explicit flag
5083  * is very useful when 'clen' is dropped.
5084  */
5085 #define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5086 #endif
5087 #define DUK_HSTRING_IS_ASCII(x) DUK_HSTRING_HAS_ASCII((x))
5088 #define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5089 
5090 #if defined(DUK_USE_STRHASH16)
5091 #define DUK_HSTRING_GET_HASH(x) ((x)->hdr.h_flags >> 16)
5092 #define DUK_HSTRING_SET_HASH(x,v) do { \
5093  (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5094  } while (0)
5095 #else
5096 #define DUK_HSTRING_GET_HASH(x) ((x)->hash)
5097 #define DUK_HSTRING_SET_HASH(x,v) do { \
5098  (x)->hash = (v); \
5099  } while (0)
5100 #endif
5101 
5102 #if defined(DUK_USE_STRLEN16)
5103 #define DUK_HSTRING_GET_BYTELEN(x) ((x)->hdr.h_strextra16)
5104 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5105  (x)->hdr.h_strextra16 = (v); \
5106  } while (0)
5107 #if defined(DUK_USE_HSTRING_CLEN)
5108 #define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen16)
5109 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5110  (x)->clen16 = (v); \
5111  } while (0)
5112 #else
5113 #define DUK_HSTRING_GET_CHARLEN(x) duk_hstring_get_charlen((x))
5114 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5115  DUK_ASSERT(0); /* should never be called */ \
5116  } while (0)
5117 #endif
5118 #else
5119 #define DUK_HSTRING_GET_BYTELEN(x) ((x)->blen)
5120 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5121  (x)->blen = (v); \
5122  } while (0)
5123 #define DUK_HSTRING_GET_CHARLEN(x) ((x)->clen)
5124 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5125  (x)->clen = (v); \
5126  } while (0)
5127 #endif
5128 
5129 #if defined(DUK_USE_HSTRING_EXTDATA)
5130 #define DUK_HSTRING_GET_EXTDATA(x) \
5131  ((x)->extdata)
5132 #define DUK_HSTRING_GET_DATA(x) \
5133  (DUK_HSTRING_HAS_EXTDATA((x)) ? \
5134  DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
5135 #else
5136 #define DUK_HSTRING_GET_DATA(x) \
5137  ((const duk_uint8_t *) ((x) + 1))
5138 #endif
5139 
5140 #define DUK_HSTRING_GET_DATA_END(x) \
5141  (DUK_HSTRING_GET_DATA((x)) + (x)->blen)
5142 
5143 /* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
5144 #define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
5145 
5146 #if defined(DUK_USE_HSTRING_ARRIDX)
5147 #define DUK_HSTRING_GET_ARRIDX_FAST(h) ((h)->arridx)
5148 #define DUK_HSTRING_GET_ARRIDX_SLOW(h) ((h)->arridx)
5149 #else
5150 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
5151  * avoids helper call if string has no array index value.
5152  */
5153 #define DUK_HSTRING_GET_ARRIDX_FAST(h) \
5154  (DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_string_helper((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
5155 
5156 /* Slower but more compact variant. */
5157 #define DUK_HSTRING_GET_ARRIDX_SLOW(h) \
5158  (duk_js_to_arrayindex_string_helper((h)))
5159 #endif
5160 
5161 /*
5162  * Misc
5163  */
5164 
5165 struct duk_hstring {
5166  /* Smaller heaphdr than for other objects, because strings are held
5167  * in string intern table which requires no link pointers. Much of
5168  * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
5169  * field in there.
5170  */
5171  duk_heaphdr_string hdr;
5172 
5173  /* Note: we could try to stuff a partial hash (e.g. 16 bits) into the
5174  * shared heap header. Good hashing needs more hash bits though.
5175  */
5176 
5177  /* string hash */
5178 #if defined(DUK_USE_STRHASH16)
5179  /* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
5180 #else
5181  duk_uint32_t hash;
5182 #endif
5183 
5184  /* precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX) */
5185 #if defined(DUK_USE_HSTRING_ARRIDX)
5186  duk_uarridx_t arridx;
5187 #endif
5188 
5189  /* length in bytes (not counting NUL term) */
5190 #if defined(DUK_USE_STRLEN16)
5191  /* placed in duk_heaphdr_string */
5192 #else
5193  duk_uint32_t blen;
5194 #endif
5195 
5196  /* length in codepoints (must be E5 compatible) */
5197 #if defined(DUK_USE_STRLEN16)
5198 #if defined(DUK_USE_HSTRING_CLEN)
5199  duk_uint16_t clen16;
5200 #else
5201  /* computed live */
5202 #endif
5203 #else
5204  duk_uint32_t clen;
5205 #endif
5206 
5207  /*
5208  * String value of 'blen+1' bytes follows (+1 for NUL termination
5209  * convenience for C API). No alignment needs to be guaranteed
5210  * for strings, but fields above should guarantee alignment-by-4
5211  * (but not alignment-by-8).
5212  */
5213 };
5214 
5215 /* The external string struct is defined even when the feature is inactive. */
5217  duk_hstring str;
5218 
5219  /*
5220  * For an external string, the NUL-terminated string data is stored
5221  * externally. The user must guarantee that data behind this pointer
5222  * doesn't change while it's used.
5223  */
5224 
5225  const duk_uint8_t *extdata;
5226 };
5227 
5228 /*
5229  * Prototypes
5230  */
5231 
5232 DUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware);
5233 
5234 #if !defined(DUK_USE_HSTRING_CLEN)
5235 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
5236 #endif
5237 
5238 #endif /* DUK_HSTRING_H_INCLUDED */
5239 /* #include duk_hobject.h */
5240 /*
5241  * Heap object representation.
5242  *
5243  * Heap objects are used for Ecmascript objects, arrays, and functions,
5244  * but also for internal control like declarative and object environment
5245  * records. Compiled functions, native functions, and threads are also
5246  * objects but with an extended C struct.
5247  *
5248  * Objects provide the required Ecmascript semantics and exotic behaviors
5249  * especially for property access.
5250  *
5251  * Properties are stored in three conceptual parts:
5252  *
5253  * 1. A linear 'entry part' contains ordered key-value-attributes triples
5254  * and is the main method of string properties.
5255  *
5256  * 2. An optional linear 'array part' is used for array objects to store a
5257  * (dense) range of [0,N[ array indexed entries with default attributes
5258  * (writable, enumerable, configurable). If the array part would become
5259  * sparse or non-default attributes are required, the array part is
5260  * abandoned and moved to the 'entry part'.
5261  *
5262  * 3. An optional 'hash part' is used to optimize lookups of the entry
5263  * part; it is used only for objects with sufficiently many properties
5264  * and can be abandoned without loss of information.
5265  *
5266  * These three conceptual parts are stored in a single memory allocated area.
5267  * This minimizes memory allocation overhead but also means that all three
5268  * parts are resized together, and makes property access a bit complicated.
5269  */
5270 
5271 #if !defined(DUK_HOBJECT_H_INCLUDED)
5272 #define DUK_HOBJECT_H_INCLUDED
5273 
5274 /* Object flag. There are currently 25 flag bits available. Make sure
5275  * this stays in sync with debugger object inspection code.
5276  */
5277 
5278 /* XXX: some flags are object subtype specific (e.g. common to all function
5279  * subtypes, duk_harray, etc) and could be reused for different subtypes.
5280  */
5281 #define DUK_HOBJECT_FLAG_EXTENSIBLE DUK_HEAPHDR_USER_FLAG(0) /* object is extensible */
5282 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE DUK_HEAPHDR_USER_FLAG(1) /* object is constructable */
5283 #define DUK_HOBJECT_FLAG_BOUNDFUNC DUK_HEAPHDR_USER_FLAG(2) /* object established using Function.prototype.bind() */
5284 #define DUK_HOBJECT_FLAG_COMPFUNC DUK_HEAPHDR_USER_FLAG(4) /* object is a compiled function (duk_hcompfunc) */
5285 #define DUK_HOBJECT_FLAG_NATFUNC DUK_HEAPHDR_USER_FLAG(5) /* object is a native function (duk_hnatfunc) */
5286 #define DUK_HOBJECT_FLAG_BUFOBJ DUK_HEAPHDR_USER_FLAG(6) /* object is a buffer object (duk_hbufobj) (always exotic) */
5287 #define DUK_HOBJECT_FLAG_THREAD DUK_HEAPHDR_USER_FLAG(7) /* object is a thread (duk_hthread) */
5288 #define DUK_HOBJECT_FLAG_ARRAY_PART DUK_HEAPHDR_USER_FLAG(8) /* object has an array part (a_size may still be 0) */
5289 #define DUK_HOBJECT_FLAG_STRICT DUK_HEAPHDR_USER_FLAG(9) /* function: function object is strict */
5290 #define DUK_HOBJECT_FLAG_NOTAIL DUK_HEAPHDR_USER_FLAG(10) /* function: function must not be tail called */
5291 #define DUK_HOBJECT_FLAG_NEWENV DUK_HEAPHDR_USER_FLAG(11) /* function: create new environment when called (see duk_hcompfunc) */
5292 #define DUK_HOBJECT_FLAG_NAMEBINDING DUK_HEAPHDR_USER_FLAG(12) /* function: create binding for func name (function templates only, used for named function expressions) */
5293 #define DUK_HOBJECT_FLAG_CREATEARGS DUK_HEAPHDR_USER_FLAG(13) /* function: create an arguments object on function call */
5294 #define DUK_HOBJECT_FLAG_ENVRECCLOSED DUK_HEAPHDR_USER_FLAG(14) /* envrec: (declarative) record is closed */
5295 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY DUK_HEAPHDR_USER_FLAG(15) /* 'Array' object, array length and index exotic behavior */
5296 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ DUK_HEAPHDR_USER_FLAG(16) /* 'String' object, array index exotic behavior */
5297 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS DUK_HEAPHDR_USER_FLAG(17) /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
5298 #define DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC DUK_HEAPHDR_USER_FLAG(18) /* Duktape/C (nativefunction) object, exotic 'length' */
5299 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ DUK_HEAPHDR_USER_FLAG(19) /* 'Proxy' object */
5300 
5301 #define DUK_HOBJECT_FLAG_CLASS_BASE DUK_HEAPHDR_USER_FLAG_NUMBER(20)
5302 #define DUK_HOBJECT_FLAG_CLASS_BITS 5
5303 
5304 #define DUK_HOBJECT_GET_CLASS_NUMBER(h) \
5305  DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
5306 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v) \
5307  DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
5308 
5309 #define DUK_HOBJECT_GET_CLASS_MASK(h) \
5310  (1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
5311 
5312 /* Macro for creating flag initializer from a class number.
5313  * Unsigned type cast is needed to avoid warnings about coercing
5314  * a signed integer to an unsigned one; the largest class values
5315  * have the highest bit (bit 31) set which causes this.
5316  */
5317 #define DUK_HOBJECT_CLASS_AS_FLAGS(v) (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
5318 
5319 /* E5 Section 8.6.2 + custom classes */
5320 #define DUK_HOBJECT_CLASS_NONE 0
5321 #define DUK_HOBJECT_CLASS_OBJECT 1
5322 #define DUK_HOBJECT_CLASS_ARRAY 2
5323 #define DUK_HOBJECT_CLASS_FUNCTION 3
5324 #define DUK_HOBJECT_CLASS_ARGUMENTS 4
5325 #define DUK_HOBJECT_CLASS_BOOLEAN 5
5326 #define DUK_HOBJECT_CLASS_DATE 6
5327 #define DUK_HOBJECT_CLASS_ERROR 7
5328 #define DUK_HOBJECT_CLASS_JSON 8
5329 #define DUK_HOBJECT_CLASS_MATH 9
5330 #define DUK_HOBJECT_CLASS_NUMBER 10
5331 #define DUK_HOBJECT_CLASS_REGEXP 11
5332 #define DUK_HOBJECT_CLASS_STRING 12
5333 #define DUK_HOBJECT_CLASS_GLOBAL 13
5334 #define DUK_HOBJECT_CLASS_SYMBOL 14
5335 #define DUK_HOBJECT_CLASS_OBJENV 15 /* custom */
5336 #define DUK_HOBJECT_CLASS_DECENV 16 /* custom */
5337 #define DUK_HOBJECT_CLASS_POINTER 17 /* custom */
5338 #define DUK_HOBJECT_CLASS_THREAD 18 /* custom; implies DUK_HOBJECT_IS_THREAD */
5339 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN 19
5340 #define DUK_HOBJECT_CLASS_ARRAYBUFFER 19 /* implies DUK_HOBJECT_IS_BUFOBJ */
5341 #define DUK_HOBJECT_CLASS_DATAVIEW 20
5342 #define DUK_HOBJECT_CLASS_INT8ARRAY 21
5343 #define DUK_HOBJECT_CLASS_UINT8ARRAY 22
5344 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY 23
5345 #define DUK_HOBJECT_CLASS_INT16ARRAY 24
5346 #define DUK_HOBJECT_CLASS_UINT16ARRAY 25
5347 #define DUK_HOBJECT_CLASS_INT32ARRAY 26
5348 #define DUK_HOBJECT_CLASS_UINT32ARRAY 27
5349 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY 28
5350 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY 29
5351 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX 29
5352 #define DUK_HOBJECT_CLASS_MAX 29
5353 
5354 /* Class masks. */
5355 #define DUK_HOBJECT_CMASK_ALL ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
5356 #define DUK_HOBJECT_CMASK_NONE (1UL << DUK_HOBJECT_CLASS_NONE)
5357 #define DUK_HOBJECT_CMASK_ARGUMENTS (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
5358 #define DUK_HOBJECT_CMASK_ARRAY (1UL << DUK_HOBJECT_CLASS_ARRAY)
5359 #define DUK_HOBJECT_CMASK_BOOLEAN (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
5360 #define DUK_HOBJECT_CMASK_DATE (1UL << DUK_HOBJECT_CLASS_DATE)
5361 #define DUK_HOBJECT_CMASK_ERROR (1UL << DUK_HOBJECT_CLASS_ERROR)
5362 #define DUK_HOBJECT_CMASK_FUNCTION (1UL << DUK_HOBJECT_CLASS_FUNCTION)
5363 #define DUK_HOBJECT_CMASK_JSON (1UL << DUK_HOBJECT_CLASS_JSON)
5364 #define DUK_HOBJECT_CMASK_MATH (1UL << DUK_HOBJECT_CLASS_MATH)
5365 #define DUK_HOBJECT_CMASK_NUMBER (1UL << DUK_HOBJECT_CLASS_NUMBER)
5366 #define DUK_HOBJECT_CMASK_OBJECT (1UL << DUK_HOBJECT_CLASS_OBJECT)
5367 #define DUK_HOBJECT_CMASK_REGEXP (1UL << DUK_HOBJECT_CLASS_REGEXP)
5368 #define DUK_HOBJECT_CMASK_STRING (1UL << DUK_HOBJECT_CLASS_STRING)
5369 #define DUK_HOBJECT_CMASK_GLOBAL (1UL << DUK_HOBJECT_CLASS_GLOBAL)
5370 #define DUK_HOBJECT_CMASK_SYMBOL (1UL << DUK_HOBJECT_CLASS_SYMBOL)
5371 #define DUK_HOBJECT_CMASK_OBJENV (1UL << DUK_HOBJECT_CLASS_OBJENV)
5372 #define DUK_HOBJECT_CMASK_DECENV (1UL << DUK_HOBJECT_CLASS_DECENV)
5373 #define DUK_HOBJECT_CMASK_POINTER (1UL << DUK_HOBJECT_CLASS_POINTER)
5374 #define DUK_HOBJECT_CMASK_THREAD (1UL << DUK_HOBJECT_CLASS_THREAD)
5375 #define DUK_HOBJECT_CMASK_ARRAYBUFFER (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
5376 #define DUK_HOBJECT_CMASK_DATAVIEW (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
5377 #define DUK_HOBJECT_CMASK_INT8ARRAY (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
5378 #define DUK_HOBJECT_CMASK_UINT8ARRAY (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
5379 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
5380 #define DUK_HOBJECT_CMASK_INT16ARRAY (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
5381 #define DUK_HOBJECT_CMASK_UINT16ARRAY (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
5382 #define DUK_HOBJECT_CMASK_INT32ARRAY (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
5383 #define DUK_HOBJECT_CMASK_UINT32ARRAY (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
5384 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
5385 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
5386 
5387 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
5388  (DUK_HOBJECT_CMASK_ARRAYBUFFER | \
5389  DUK_HOBJECT_CMASK_DATAVIEW | \
5390  DUK_HOBJECT_CMASK_INT8ARRAY | \
5391  DUK_HOBJECT_CMASK_UINT8ARRAY | \
5392  DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
5393  DUK_HOBJECT_CMASK_INT16ARRAY | \
5394  DUK_HOBJECT_CMASK_UINT16ARRAY | \
5395  DUK_HOBJECT_CMASK_INT32ARRAY | \
5396  DUK_HOBJECT_CMASK_UINT32ARRAY | \
5397  DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
5398  DUK_HOBJECT_CMASK_FLOAT64ARRAY)
5399 
5400 #define DUK_HOBJECT_IS_OBJENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
5401 #define DUK_HOBJECT_IS_DECENV(h) (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
5402 #define DUK_HOBJECT_IS_ENV(h) (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
5403 #define DUK_HOBJECT_IS_ARRAY(h) DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)) /* Rely on class Array <=> exotic Array */
5404 #define DUK_HOBJECT_IS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
5405 #define DUK_HOBJECT_IS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
5406 #define DUK_HOBJECT_IS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
5407 #define DUK_HOBJECT_IS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
5408 #define DUK_HOBJECT_IS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
5409 
5410 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
5411  DUK_HOBJECT_FLAG_COMPFUNC | \
5412  DUK_HOBJECT_FLAG_NATFUNC)
5413 
5414 #define DUK_HOBJECT_IS_FUNCTION(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
5415  DUK_HOBJECT_FLAG_BOUNDFUNC | \
5416  DUK_HOBJECT_FLAG_COMPFUNC | \
5417  DUK_HOBJECT_FLAG_NATFUNC)
5418 
5419 #define DUK_HOBJECT_IS_CALLABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
5420  DUK_HOBJECT_FLAG_BOUNDFUNC | \
5421  DUK_HOBJECT_FLAG_COMPFUNC | \
5422  DUK_HOBJECT_FLAG_NATFUNC)
5423 
5424 /* Object has any exotic behavior(s). */
5425 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
5426  DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
5427  DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
5428  DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
5429  DUK_HOBJECT_FLAG_BUFOBJ | \
5430  DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
5431 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
5432 
5433 /* Object has any virtual properties (not counting Proxy behavior). */
5434 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
5435  DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
5436  DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC | \
5437  DUK_HOBJECT_FLAG_BUFOBJ)
5438 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
5439 
5440 #define DUK_HOBJECT_HAS_EXTENSIBLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
5441 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
5442 #define DUK_HOBJECT_HAS_BOUNDFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
5443 #define DUK_HOBJECT_HAS_COMPFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
5444 #define DUK_HOBJECT_HAS_NATFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
5445 #define DUK_HOBJECT_HAS_BUFOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
5446 #define DUK_HOBJECT_HAS_THREAD(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
5447 #define DUK_HOBJECT_HAS_ARRAY_PART(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
5448 #define DUK_HOBJECT_HAS_STRICT(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
5449 #define DUK_HOBJECT_HAS_NOTAIL(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
5450 #define DUK_HOBJECT_HAS_NEWENV(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
5451 #define DUK_HOBJECT_HAS_NAMEBINDING(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
5452 #define DUK_HOBJECT_HAS_CREATEARGS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
5453 #define DUK_HOBJECT_HAS_ENVRECCLOSED(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
5454 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
5455 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
5456 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
5457 #define DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
5458 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
5459 
5460 #define DUK_HOBJECT_SET_EXTENSIBLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
5461 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
5462 #define DUK_HOBJECT_SET_BOUNDFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
5463 #define DUK_HOBJECT_SET_COMPFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
5464 #define DUK_HOBJECT_SET_NATFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
5465 #define DUK_HOBJECT_SET_BUFOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
5466 #define DUK_HOBJECT_SET_THREAD(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
5467 #define DUK_HOBJECT_SET_ARRAY_PART(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
5468 #define DUK_HOBJECT_SET_STRICT(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
5469 #define DUK_HOBJECT_SET_NOTAIL(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
5470 #define DUK_HOBJECT_SET_NEWENV(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
5471 #define DUK_HOBJECT_SET_NAMEBINDING(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
5472 #define DUK_HOBJECT_SET_CREATEARGS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
5473 #define DUK_HOBJECT_SET_ENVRECCLOSED(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
5474 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
5475 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
5476 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
5477 #define DUK_HOBJECT_SET_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
5478 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
5479 
5480 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
5481 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
5482 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
5483 #define DUK_HOBJECT_CLEAR_COMPFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
5484 #define DUK_HOBJECT_CLEAR_NATFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
5485 #define DUK_HOBJECT_CLEAR_BUFOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
5486 #define DUK_HOBJECT_CLEAR_THREAD(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_THREAD)
5487 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
5488 #define DUK_HOBJECT_CLEAR_STRICT(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
5489 #define DUK_HOBJECT_CLEAR_NOTAIL(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
5490 #define DUK_HOBJECT_CLEAR_NEWENV(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
5491 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
5492 #define DUK_HOBJECT_CLEAR_CREATEARGS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
5493 #define DUK_HOBJECT_CLEAR_ENVRECCLOSED(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ENVRECCLOSED)
5494 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
5495 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
5496 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
5497 #define DUK_HOBJECT_CLEAR_EXOTIC_DUKFUNC(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC)
5498 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
5499 
5500 /* Flags used for property attributes in duk_propdesc and packed flags.
5501  * Must fit into 8 bits.
5502  */
5503 #define DUK_PROPDESC_FLAG_WRITABLE (1 << 0) /* E5 Section 8.6.1 */
5504 #define DUK_PROPDESC_FLAG_ENUMERABLE (1 << 1) /* E5 Section 8.6.1 */
5505 #define DUK_PROPDESC_FLAG_CONFIGURABLE (1 << 2) /* E5 Section 8.6.1 */
5506 #define DUK_PROPDESC_FLAG_ACCESSOR (1 << 3) /* accessor */
5507 #define DUK_PROPDESC_FLAG_VIRTUAL (1 << 4) /* property is virtual: used in duk_propdesc, never stored
5508  * (used by e.g. buffer virtual properties)
5509  */
5510 #define DUK_PROPDESC_FLAGS_MASK (DUK_PROPDESC_FLAG_WRITABLE | \
5511  DUK_PROPDESC_FLAG_ENUMERABLE | \
5512  DUK_PROPDESC_FLAG_CONFIGURABLE | \
5513  DUK_PROPDESC_FLAG_ACCESSOR)
5514 
5515 /* Additional flags which are passed in the same flags argument as property
5516  * flags but are not stored in object properties.
5517  */
5518 #define DUK_PROPDESC_FLAG_NO_OVERWRITE (1 << 4) /* internal define property: skip write silently if exists */
5519 
5520 /* Convenience defines for property attributes. */
5521 #define DUK_PROPDESC_FLAGS_NONE 0
5522 #define DUK_PROPDESC_FLAGS_W (DUK_PROPDESC_FLAG_WRITABLE)
5523 #define DUK_PROPDESC_FLAGS_E (DUK_PROPDESC_FLAG_ENUMERABLE)
5524 #define DUK_PROPDESC_FLAGS_C (DUK_PROPDESC_FLAG_CONFIGURABLE)
5525 #define DUK_PROPDESC_FLAGS_WE (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
5526 #define DUK_PROPDESC_FLAGS_WC (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
5527 #define DUK_PROPDESC_FLAGS_EC (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
5528 #define DUK_PROPDESC_FLAGS_WEC (DUK_PROPDESC_FLAG_WRITABLE | \
5529  DUK_PROPDESC_FLAG_ENUMERABLE | \
5530  DUK_PROPDESC_FLAG_CONFIGURABLE)
5531 
5532 /* Flags for duk_hobject_get_own_propdesc() and variants. */
5533 #define DUK_GETDESC_FLAG_PUSH_VALUE (1 << 0) /* push value to stack */
5534 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP (1 << 1) /* don't throw for prototype loop */
5535 
5536 /*
5537  * Macro for object validity check
5538  *
5539  * Assert for currently guaranteed relations between flags, for instance.
5540  */
5541 
5542 #define DUK_ASSERT_HOBJECT_VALID(h) do { \
5543  DUK_ASSERT((h) != NULL); \
5544  DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
5545  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
5546  DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \
5547  (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
5548  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
5549  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
5550  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
5551  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
5552  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
5553  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
5554  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
5555  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
5556  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
5557  DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
5558  /* Object is an Array <=> object has exotic array behavior */ \
5559  DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \
5560  (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \
5561  } while (0)
5562 
5563 /*
5564  * Macros to access the 'props' allocation.
5565  */
5566 
5567 #if defined(DUK_USE_HEAPPTR16)
5568 #define DUK_HOBJECT_GET_PROPS(heap,h) \
5569  ((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
5570 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
5571  ((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
5572  } while (0)
5573 #else
5574 #define DUK_HOBJECT_GET_PROPS(heap,h) \
5575  ((h)->props)
5576 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
5577  (h)->props = (duk_uint8_t *) (x); \
5578  } while (0)
5579 #endif
5580 
5581 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
5582 /* LAYOUT 1 */
5583 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5584  ((duk_hstring **) (void *) ( \
5585  DUK_HOBJECT_GET_PROPS((heap), (h)) \
5586  ))
5587 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5588  ((duk_propvalue *) (void *) ( \
5589  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5590  DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
5591  ))
5592 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5593  ((duk_uint8_t *) (void *) ( \
5594  DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
5595  ))
5596 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
5597  ((duk_tval *) (void *) ( \
5598  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5599  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
5600  ))
5601 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
5602  ((duk_uint32_t *) (void *) ( \
5603  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5604  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5605  DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5606  ))
5607 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5608  ( \
5609  (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5610  (n_arr) * sizeof(duk_tval) + \
5611  (n_hash) * sizeof(duk_uint32_t) \
5612  )
5613 #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 { \
5614  (set_e_k) = (duk_hstring **) (void *) (p_base); \
5615  (set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
5616  (set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
5617  (set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
5618  (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
5619  } while (0)
5620 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
5621 /* LAYOUT 2 */
5622 #if (DUK_USE_ALIGN_BY == 4)
5623 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
5624 #elif (DUK_USE_ALIGN_BY == 8)
5625 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
5626 #elif (DUK_USE_ALIGN_BY == 1)
5627 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
5628 #else
5629 #error invalid DUK_USE_ALIGN_BY
5630 #endif
5631 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5632  ((duk_hstring **) (void *) ( \
5633  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5634  DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5635  ))
5636 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5637  ((duk_propvalue *) (void *) ( \
5638  DUK_HOBJECT_GET_PROPS((heap), (h)) \
5639  ))
5640 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5641  ((duk_uint8_t *) (void *) ( \
5642  DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
5643  ))
5644 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
5645  ((duk_tval *) (void *) ( \
5646  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5647  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5648  DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
5649  ))
5650 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
5651  ((duk_uint32_t *) (void *) ( \
5652  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5653  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5654  DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
5655  DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5656  ))
5657 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5658  ( \
5659  (n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
5660  DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
5661  (n_arr) * sizeof(duk_tval) + \
5662  (n_hash) * sizeof(duk_uint32_t) \
5663  )
5664 #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 { \
5665  (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5666  (set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
5667  (set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
5668  (set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
5669  sizeof(duk_uint8_t) * (n_ent) + \
5670  DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
5671  (set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
5672  } while (0)
5673 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
5674 /* LAYOUT 3 */
5675 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
5676  ((duk_hstring **) (void *) ( \
5677  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5678  DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
5679  DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5680  ))
5681 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
5682  ((duk_propvalue *) (void *) ( \
5683  DUK_HOBJECT_GET_PROPS((heap), (h)) \
5684  ))
5685 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
5686  ((duk_uint8_t *) (void *) ( \
5687  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5688  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5689  DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \
5690  DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
5691  ))
5692 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
5693  ((duk_tval *) (void *) ( \
5694  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5695  DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
5696  ))
5697 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
5698  ((duk_uint32_t *) (void *) ( \
5699  DUK_HOBJECT_GET_PROPS((heap), (h)) + \
5700  DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
5701  DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
5702  ))
5703 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
5704  ( \
5705  (n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
5706  (n_arr) * sizeof(duk_tval) + \
5707  (n_hash) * sizeof(duk_uint32_t) \
5708  )
5709 #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 { \
5710  (set_e_pv) = (duk_propvalue *) (void *) (p_base); \
5711  (set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
5712  (set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
5713  (set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
5714  (set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
5715  } while (0)
5716 #else
5717 #error invalid hobject layout defines
5718 #endif /* hobject property layout */
5719 
5720 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
5721  DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
5722 
5723 #define DUK_HOBJECT_E_GET_KEY(heap,h,i) (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5724 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
5725 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i) (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5726 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
5727 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5728 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
5729 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5730 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
5731 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i) (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5732 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
5733 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i) (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5734 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
5735 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i) (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5736 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i) (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
5737 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i) (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5738 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i) (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
5739 
5740 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k) do { \
5741  DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
5742  } while (0)
5743 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v) do { \
5744  DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
5745  } while (0)
5746 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v) do { \
5747  DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
5748  } while (0)
5749 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v) do { \
5750  DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
5751  } while (0)
5752 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v) do { \
5753  DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
5754  } while (0)
5755 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f) do { \
5756  DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
5757  } while (0)
5758 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v) do { \
5759  DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
5760  } while (0)
5761 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
5762  DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v)) /* alias for above */
5763 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v) do { \
5764  DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
5765  } while (0)
5766 
5767 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask) do { \
5768  DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
5769  } while (0)
5770 
5771 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask) do { \
5772  DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
5773  } while (0)
5774 
5775 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5776 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5777 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5778 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5779 
5780 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5781 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5782 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5783 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i) DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5784 
5785 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
5786 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
5787 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
5788 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i) DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
5789 
5790 #define DUK_PROPDESC_IS_WRITABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
5791 #define DUK_PROPDESC_IS_ENUMERABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
5792 #define DUK_PROPDESC_IS_CONFIGURABLE(p) (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
5793 #define DUK_PROPDESC_IS_ACCESSOR(p) (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
5794 
5795 #define DUK_HOBJECT_HASHIDX_UNUSED 0xffffffffUL
5796 #define DUK_HOBJECT_HASHIDX_DELETED 0xfffffffeUL
5797 
5798 /*
5799  * Macros for accessing size fields
5800  */
5801 
5802 #if defined(DUK_USE_OBJSIZES16)
5803 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
5804 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
5805 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
5806 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
5807 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
5808 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
5809 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
5810 #if defined(DUK_USE_HOBJECT_HASH_PART)
5811 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
5812 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
5813 #else
5814 #define DUK_HOBJECT_GET_HSIZE(h) 0
5815 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5816 #endif
5817 #else
5818 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
5819 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
5820 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
5821 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
5822 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
5823 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
5824 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
5825 #if defined(DUK_USE_HOBJECT_HASH_PART)
5826 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
5827 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
5828 #else
5829 #define DUK_HOBJECT_GET_HSIZE(h) 0
5830 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
5831 #endif
5832 #endif
5833 
5834 /*
5835  * Misc
5836  */
5837 
5838 /* Maximum prototype traversal depth. Sanity limit which handles e.g.
5839  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
5840  */
5841 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY 10000L
5842 
5843 /* Maximum traversal depth for "bound function" chains. */
5844 #define DUK_HOBJECT_BOUND_CHAIN_SANITY 10000L
5845 
5846 /*
5847  * Ecmascript [[Class]]
5848  */
5849 
5850 /* range check not necessary because all 4-bit values are mapped */
5851 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n) duk_class_number_to_stridx[(n)]
5852 
5853 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h) \
5854  DUK_HEAP_GET_STRING( \
5855  (heap), \
5856  DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
5857  )
5858 
5859 /*
5860  * Macros for property handling
5861  */
5862 
5863 #if defined(DUK_USE_HEAPPTR16)
5864 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5865  ((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
5866 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5867  (h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
5868  } while (0)
5869 #else
5870 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
5871  ((h)->prototype)
5872 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
5873  (h)->prototype = (x); \
5874  } while (0)
5875 #endif
5876 
5877 /* note: this updates refcounts */
5878 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p) duk_hobject_set_prototype_updref((thr), (h), (p))
5879 
5880 /*
5881  * Resizing and hash behavior
5882  */
5883 
5884 /* Sanity limit on max number of properties (allocated, not necessarily used).
5885  * This is somewhat arbitrary, but if we're close to 2**32 properties some
5886  * algorithms will fail (e.g. hash size selection, next prime selection).
5887  * Also, we use negative array/entry table indices to indicate 'not found',
5888  * so anything above 0x80000000 will cause trouble now.
5889  */
5890 #if defined(DUK_USE_OBJSIZES16)
5891 #define DUK_HOBJECT_MAX_PROPERTIES 0x0000ffffUL
5892 #else
5893 #define DUK_HOBJECT_MAX_PROPERTIES 0x7fffffffUL /* 2**31-1 ~= 2G properties */
5894 #endif
5895 
5896 /* higher value conserves memory; also note that linear scan is cache friendly */
5897 #define DUK_HOBJECT_E_USE_HASH_LIMIT 32
5898 
5899 /* hash size relative to entries size: for value X, approx. hash_prime(e_size + e_size / X) */
5900 #define DUK_HOBJECT_H_SIZE_DIVISOR 4 /* hash size approx. 1.25 times entries size */
5901 
5902 /* if new_size < L * old_size, resize without abandon check; L = 3-bit fixed point, e.g. 9 -> 9/8 = 112.5% */
5903 #define DUK_HOBJECT_A_FAST_RESIZE_LIMIT 9 /* 112.5%, i.e. new size less than 12.5% higher -> fast resize */
5904 
5905 /* if density < L, abandon array part, L = 3-bit fixed point, e.g. 2 -> 2/8 = 25% */
5906 /* limit is quite low: one array entry is 8 bytes, one normal entry is 4+1+8+4 = 17 bytes (with hash entry) */
5907 #define DUK_HOBJECT_A_ABANDON_LIMIT 2 /* 25%, i.e. less than 25% used -> abandon */
5908 
5909 /* internal align target for props allocation, must be 2*n for some n */
5910 #if (DUK_USE_ALIGN_BY == 4)
5911 #define DUK_HOBJECT_ALIGN_TARGET 4
5912 #elif (DUK_USE_ALIGN_BY == 8)
5913 #define DUK_HOBJECT_ALIGN_TARGET 8
5914 #elif (DUK_USE_ALIGN_BY == 1)
5915 #define DUK_HOBJECT_ALIGN_TARGET 1
5916 #else
5917 #error invalid DUK_USE_ALIGN_BY
5918 #endif
5919 
5920 /* controls for minimum entry part growth */
5921 #define DUK_HOBJECT_E_MIN_GROW_ADD 16
5922 #define DUK_HOBJECT_E_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5923 
5924 /* controls for minimum array part growth */
5925 #define DUK_HOBJECT_A_MIN_GROW_ADD 16
5926 #define DUK_HOBJECT_A_MIN_GROW_DIVISOR 8 /* 2^3 -> 1/8 = 12.5% min growth */
5927 
5928 /* probe sequence */
5929 #define DUK_HOBJECT_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
5930 #define DUK_HOBJECT_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
5931 
5932 /*
5933  * PC-to-line constants
5934  */
5935 
5936 #define DUK_PC2LINE_SKIP 64
5937 
5938 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
5939 #define DUK_PC2LINE_MAX_DIFF_LENGTH (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
5940 
5941 /*
5942  * Struct defs
5943  */
5944 
5946  duk_hobject *get;
5947  duk_hobject *set;
5948 };
5949 
5951  /* The get/set pointers could be 16-bit pointer compressed but it
5952  * would make no difference on 32-bit platforms because duk_tval is
5953  * 8 bytes or more anyway.
5954  */
5955  duk_tval v;
5956  duk_propaccessor a;
5957 };
5958 
5960  /* read-only values 'lifted' for ease of use */
5961  duk_small_int_t flags;
5962  duk_hobject *get;
5963  duk_hobject *set;
5964 
5965  /* for updating (all are set to < 0 for virtual properties) */
5966  duk_int_t e_idx; /* prop index in 'entry part', < 0 if not there */
5967  duk_int_t h_idx; /* prop index in 'hash part', < 0 if not there */
5968  duk_int_t a_idx; /* prop index in 'array part', < 0 if not there */
5969 };
5970 
5971 struct duk_hobject {
5972  duk_heaphdr hdr;
5973 
5974  /*
5975  * 'props' contains {key,value,flags} entries, optional array entries, and
5976  * an optional hash lookup table for non-array entries in a single 'sliced'
5977  * allocation. There are several layout options, which differ slightly in
5978  * generated code size/speed and alignment/padding; duk_features.h selects
5979  * the layout used.
5980  *
5981  * Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
5982  *
5983  * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5984  * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5985  * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
5986  * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5987  * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5988  * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5989  *
5990  * Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
5991  *
5992  * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
5993  * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
5994  * e_size * sizeof(duk_uint8_t) + pad bytes of entry flags (e_next gc reachable)
5995  * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
5996  * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
5997  * 0xffffffffUL = unused, 0xfffffffeUL = deleted
5998  *
5999  * Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6000  *
6001  * e_size * sizeof(duk_propvalue) bytes of entry values (e_next gc reachable)
6002  * a_size * sizeof(duk_tval) bytes of (opt) array values (plain only) (all gc reachable)
6003  * e_size * sizeof(duk_hstring *) bytes of entry keys (e_next gc reachable)
6004  * h_size * sizeof(duk_uint32_t) bytes of (opt) hash indexes to entries (e_size),
6005  * 0xffffffffUL = unused, 0xfffffffeUL = deleted
6006  * e_size * sizeof(duk_uint8_t) bytes of entry flags (e_next gc reachable)
6007  *
6008  * In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6009  * requiring 4 or 8 byte alignment. This ensures proper alignment
6010  * for the entries, at the cost of memory footprint. However, it's
6011  * probably preferable to use another layout on such platforms instead.
6012  *
6013  * In layout 2, the key and value parts are swapped to avoid padding
6014  * the key array on platforms requiring alignment by 8. The flags part
6015  * is padded to get alignment for array entries. The 'e_next' count does
6016  * not need to be rounded as in layout 1.
6017  *
6018  * In layout 3, entry values and array values are always aligned properly,
6019  * and assuming pointers are at most 8 bytes, so are the entry keys. Hash
6020  * indices will be properly aligned (assuming pointers are at least 4 bytes).
6021  * Finally, flags don't need additional alignment. This layout provides
6022  * compact allocations without padding (even on platforms with alignment
6023  * requirements) at the cost of a bit slower lookups.
6024  *
6025  * Objects with few keys don't have a hash index; keys are looked up linearly,
6026  * which is cache efficient because the keys are consecutive. Larger objects
6027  * have a hash index part which contains integer indexes to the entries part.
6028  *
6029  * A single allocation reduces memory allocation overhead but requires more
6030  * work when any part needs to be resized. A sliced allocation for entries
6031  * makes linear key matching faster on most platforms (more locality) and
6032  * skimps on flags size (which would be followed by 3 bytes of padding in
6033  * most architectures if entries were placed in a struct).
6034  *
6035  * 'props' also contains internal properties distinguished with a non-BMP
6036  * prefix. Often used properties should be placed early in 'props' whenever
6037  * possible to make accessing them as fast a possible.
6038  */
6039 
6040 #if defined(DUK_USE_HEAPPTR16)
6041  /* Located in duk_heaphdr h_extra16. Subclasses of duk_hobject (like
6042  * duk_hcompfunc) are not free to use h_extra16 for this reason.
6043  */
6044 #else
6045  duk_uint8_t *props;
6046 #endif
6047 
6048  /* prototype: the only internal property lifted outside 'e' as it is so central */
6049 #if defined(DUK_USE_HEAPPTR16)
6050  duk_uint16_t prototype16;
6051 #else
6052  duk_hobject *prototype;
6053 #endif
6054 
6055 #if defined(DUK_USE_OBJSIZES16)
6056  duk_uint16_t e_size16;
6057  duk_uint16_t e_next16;
6058  duk_uint16_t a_size16;
6059 #if defined(DUK_USE_HOBJECT_HASH_PART)
6060  duk_uint16_t h_size16;
6061 #endif
6062 #else
6063  duk_uint32_t e_size; /* entry part size */
6064  duk_uint32_t e_next; /* index for next new key ([0,e_next[ are gc reachable) */
6065  duk_uint32_t a_size; /* array part size (entirely gc reachable) */
6066 #if defined(DUK_USE_HOBJECT_HASH_PART)
6067  duk_uint32_t h_size; /* hash part size or 0 if unused */
6068 #endif
6069 #endif
6070 };
6071 
6072 /*
6073  * Exposed data
6074  */
6075 
6076 #if !defined(DUK_SINGLE_FILE)
6077 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6078 #endif /* !DUK_SINGLE_FILE */
6079 
6080 /*
6081  * Prototypes
6082  */
6083 
6084 /* alloc and init */
6085 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6086 #if 0 /* unused */
6087 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags);
6088 #endif
6089 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6090 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6091 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6092 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6093 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6094 #endif
6095 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6096 
6097 /* resize */
6098 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
6099  duk_hobject *obj,
6100  duk_uint32_t new_e_size,
6101  duk_uint32_t new_a_size,
6102  duk_uint32_t new_h_size,
6103  duk_bool_t abandon_array);
6104 
6105 /* low-level property functions */
6106 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);
6107 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
6108 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);
6109 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
6110 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);
6111 
6112 /* XXX: when optimizing for guaranteed property slots, use a guaranteed
6113  * slot for internal value; this call can then access it directly.
6114  */
6115 #define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
6116  duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
6117 
6118 /* core property functions */
6119 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6120 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);
6121 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);
6122 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6123 
6124 /* internal property functions */
6125 #define DUK_DELPROP_FLAG_THROW (1 << 0)
6126 #define DUK_DELPROP_FLAG_FORCE (1 << 1)
6127 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6128 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
6129 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6130 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);
6131 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
6132 
6133 /* helpers for defineProperty() and defineProperties() */
6134 DUK_INTERNAL_DECL
6135 void duk_hobject_prepare_property_descriptor(duk_context *ctx,
6136  duk_idx_t idx_in,
6137  duk_uint_t *out_defprop_flags,
6138  duk_idx_t *out_idx_value,
6139  duk_hobject **out_getter,
6140  duk_hobject **out_setter);
6141 DUK_INTERNAL_DECL
6142 duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
6143  duk_uint_t defprop_flags,
6144  duk_hobject *obj,
6145  duk_hstring *key,
6146  duk_idx_t idx_value,
6147  duk_hobject *get,
6148  duk_hobject *set,
6149  duk_bool_t throw_flag);
6150 
6151 /* Object built-in methods */
6152 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_context *ctx, duk_idx_t obj_idx);
6153 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
6154 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
6155 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags);
6156 
6157 /* internal properties */
6158 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
6159 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
6160 
6161 /* hobject management functions */
6162 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
6163 
6164 /* ES2015 proxy */
6165 #if defined(DUK_USE_ES6_PROXY)
6166 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
6167 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj);
6168 #endif
6169 
6170 /* enumeration */
6171 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags);
6172 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags);
6173 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value);
6174 
6175 /* macros */
6176 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
6177 
6178 /* finalization */
6179 #if defined(DUK_USE_FINALIZER_SUPPORT)
6180 DUK_INTERNAL_DECL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj);
6181 #endif
6182 
6183 /* pc2line */
6184 #if defined(DUK_USE_PC2LINE)
6185 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
6186 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc);
6187 #endif
6188 
6189 /* misc */
6190 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);
6191 
6192 #if !defined(DUK_USE_OBJECT_BUILTIN)
6193 /* These declarations are needed when related built-in is disabled and
6194  * genbuiltins.py won't automatically emit the declerations.
6195  */
6196 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
6197 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
6198 #endif
6199 
6200 #endif /* DUK_HOBJECT_H_INCLUDED */
6201 /* #include duk_hcompfunc.h */
6202 /*
6203  * Heap compiled function (Ecmascript function) representation.
6204  *
6205  * There is a single data buffer containing the Ecmascript function's
6206  * bytecode, constants, and inner functions.
6207  */
6208 
6209 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
6210 #define DUK_HCOMPFUNC_H_INCLUDED
6211 
6212 /*
6213  * Field accessor macros
6214  */
6215 
6216 /* XXX: casts could be improved, especially for GET/SET DATA */
6217 
6218 #if defined(DUK_USE_HEAPPTR16)
6219 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
6220  ((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
6221 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
6222  (h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6223  } while (0)
6224 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h) \
6225  ((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
6226 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
6227  (h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6228  } while (0)
6229 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) \
6230  ((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
6231 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
6232  (h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6233  } while (0)
6234 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h) \
6235  ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
6236 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
6237  (h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6238  } while (0)
6239 #define DUK_HCOMPFUNC_GET_VARENV(heap,h) \
6240  ((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
6241 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
6242  (h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
6243  } while (0)
6244 #else
6245 #define DUK_HCOMPFUNC_GET_DATA(heap,h) ((duk_hbuffer_fixed *) (void *) (h)->data)
6246 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
6247  (h)->data = (duk_hbuffer *) (v); \
6248  } while (0)
6249 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h) ((h)->funcs)
6250 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v) do { \
6251  (h)->funcs = (v); \
6252  } while (0)
6253 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h) ((h)->bytecode)
6254 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v) do { \
6255  (h)->bytecode = (v); \
6256  } while (0)
6257 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h) ((h)->lex_env)
6258 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v) do { \
6259  (h)->lex_env = (v); \
6260  } while (0)
6261 #define DUK_HCOMPFUNC_GET_VARENV(heap,h) ((h)->var_env)
6262 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v) do { \
6263  (h)->var_env = (v); \
6264  } while (0)
6265 #endif
6266 
6267 /*
6268  * Accessor macros for function specific data areas
6269  */
6270 
6271 /* Note: assumes 'data' is always a fixed buffer */
6272 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h) \
6273  DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
6274 
6275 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h) \
6276  ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
6277 
6278 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h) \
6279  DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
6280 
6281 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h) \
6282  DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
6283 
6284 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h) \
6285  ((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
6286 
6287 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h) \
6288  ((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
6289 
6290 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
6291 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h) \
6292  ((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
6293  DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
6294 
6295 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h) \
6296  ( \
6297  (duk_size_t) \
6298  ( \
6299  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
6300  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
6301  ) \
6302  )
6303 
6304 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h) \
6305  ( \
6306  (duk_size_t) \
6307  ( \
6308  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
6309  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
6310  ) \
6311  )
6312 
6313 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h) \
6314  ( \
6315  (duk_size_t) \
6316  ( \
6317  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
6318  ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
6319  ) \
6320  )
6321 
6322 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h) \
6323  ((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
6324 
6325 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h) \
6326  ((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
6327 
6328 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h) \
6329  ((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
6330 
6331 
6332 /*
6333  * Main struct
6334  */
6335 
6337  /* shared object part */
6338  duk_hobject obj;
6339 
6340  /*
6341  * Pointers to function data area for faster access. Function
6342  * data is a buffer shared between all closures of the same
6343  * "template" function. The data buffer is always fixed (non-
6344  * dynamic, hence stable), with a layout as follows:
6345  *
6346  * constants (duk_tval)
6347  * inner functions (duk_hobject *)
6348  * bytecode (duk_instr_t)
6349  *
6350  * Note: bytecode end address can be computed from 'data' buffer
6351  * size. It is not strictly necessary functionally, assuming
6352  * bytecode never jumps outside its allocated area. However,
6353  * it's a safety/robustness feature for avoiding the chance of
6354  * executing random data as bytecode due to a compiler error.
6355  *
6356  * Note: values in the data buffer must be incref'd (they will
6357  * be decref'd on release) for every compiledfunction referring
6358  * to the 'data' element.
6359  */
6360 
6361  /* Data area, fixed allocation, stable data ptrs. */
6362 #if defined(DUK_USE_HEAPPTR16)
6363  duk_uint16_t data16;
6364 #else
6365  duk_hbuffer *data;
6366 #endif
6367 
6368  /* No need for constants pointer (= same as data).
6369  *
6370  * When using 16-bit packing alignment to 4 is nice. 'funcs' will be
6371  * 4-byte aligned because 'constants' are duk_tvals. For now the
6372  * inner function pointers are not compressed, so that 'bytecode' will
6373  * also be 4-byte aligned.
6374  */
6375 #if defined(DUK_USE_HEAPPTR16)
6376  duk_uint16_t funcs16;
6377  duk_uint16_t bytecode16;
6378 #else
6379  duk_hobject **funcs;
6380  duk_instr_t *bytecode;
6381 #endif
6382 
6383  /* Lexenv: lexical environment of closure, NULL for templates.
6384  * Varenv: variable environment of closure, NULL for templates.
6385  */
6386 #if defined(DUK_USE_HEAPPTR16)
6387  duk_uint16_t lex_env16;
6388  duk_uint16_t var_env16;
6389 #else
6390  duk_hobject *lex_env;
6391  duk_hobject *var_env;
6392 #endif
6393 
6394  /*
6395  * 'nregs' registers are allocated on function entry, at most 'nargs'
6396  * are initialized to arguments, and the rest to undefined. Arguments
6397  * above 'nregs' are not mapped to registers. All registers in the
6398  * active stack range must be initialized because they are GC reachable.
6399  * 'nargs' is needed so that if the function is given more than 'nargs'
6400  * arguments, the additional arguments do not 'clobber' registers
6401  * beyond 'nregs' which must be consistently initialized to undefined.
6402  *
6403  * Usually there is no need to know which registers are mapped to
6404  * local variables. Registers may be allocated to variable in any
6405  * way (even including gaps). However, a register-variable mapping
6406  * must be the same for the duration of the function execution and
6407  * the register cannot be used for anything else.
6408  *
6409  * When looking up variables by name, the '_Varmap' map is used.
6410  * When an activation closes, registers mapped to arguments are
6411  * copied into the environment record based on the same map. The
6412  * reverse map (from register to variable) is not currently needed
6413  * at run time, except for debugging, so it is not maintained.
6414  */
6415 
6416  duk_uint16_t nregs; /* regs to allocate */
6417  duk_uint16_t nargs; /* number of arguments allocated to regs */
6418 
6419  /*
6420  * Additional control information is placed into the object itself
6421  * as internal properties to avoid unnecessary fields for the
6422  * majority of functions. The compiler tries to omit internal
6423  * control fields when possible.
6424  *
6425  * Function templates:
6426  *
6427  * {
6428  * name: "func", // declaration, named function expressions
6429  * fileName: <debug info for creating nice errors>
6430  * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
6431  * _Formals: [ "arg1", "arg2" ],
6432  * _Source: "function func(arg1, arg2) { ... }",
6433  * _Pc2line: <debug info for pc-to-line mapping>,
6434  * }
6435  *
6436  * Function instances:
6437  *
6438  * {
6439  * length: 2,
6440  * prototype: { constructor: <func> },
6441  * caller: <thrower>,
6442  * arguments: <thrower>,
6443  * name: "func", // declaration, named function expressions
6444  * fileName: <debug info for creating nice errors>
6445  * _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
6446  * _Formals: [ "arg1", "arg2" ],
6447  * _Source: "function func(arg1, arg2) { ... }",
6448  * _Pc2line: <debug info for pc-to-line mapping>,
6449  * }
6450  *
6451  * More detailed description of these properties can be found
6452  * in the documentation.
6453  */
6454 
6455 #if defined(DUK_USE_DEBUGGER_SUPPORT)
6456  /* Line number range for function. Needed during debugging to
6457  * determine active breakpoints.
6458  */
6459  duk_uint32_t start_line;
6460  duk_uint32_t end_line;
6461 #endif
6462 };
6463 
6464 #endif /* DUK_HCOMPFUNC_H_INCLUDED */
6465 /* #include duk_hnatfunc.h */
6466 /*
6467  * Heap native function representation.
6468  */
6469 
6470 #if !defined(DUK_HNATFUNC_H_INCLUDED)
6471 #define DUK_HNATFUNC_H_INCLUDED
6472 
6473 #define DUK_HNATFUNC_NARGS_VARARGS ((duk_int16_t) -1)
6474 #define DUK_HNATFUNC_NARGS_MAX ((duk_int16_t) 0x7fff)
6475 
6477  /* shared object part */
6478  duk_hobject obj;
6479 
6480  duk_c_function func;
6481  duk_int16_t nargs;
6482  duk_int16_t magic;
6483 
6484  /* The 'magic' field allows an opaque 16-bit field to be accessed by the
6485  * Duktape/C function. This allows, for instance, the same native function
6486  * to be used for a set of very similar functions, with the 'magic' field
6487  * providing the necessary non-argument flags / values to guide the behavior
6488  * of the native function. The value is signed on purpose: it is easier to
6489  * convert a signed value to unsigned (simply AND with 0xffff) than vice
6490  * versa.
6491  *
6492  * Note: cannot place nargs/magic into the heaphdr flags, because
6493  * duk_hobject takes almost all flags already (and needs the spare).
6494  */
6495 };
6496 
6497 #endif /* DUK_HNATFUNC_H_INCLUDED */
6498 /* #include duk_hbufobj.h */
6499 /*
6500  * Heap Buffer object representation. Used for all Buffer variants.
6501  */
6502 
6503 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
6504 #define DUK_HBUFOBJ_H_INCLUDED
6505 
6506 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6507 
6508 /* All element accessors are host endian now (driven by TypedArray spec). */
6509 #define DUK_HBUFOBJ_ELEM_UINT8 0
6510 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1
6511 #define DUK_HBUFOBJ_ELEM_INT8 2
6512 #define DUK_HBUFOBJ_ELEM_UINT16 3
6513 #define DUK_HBUFOBJ_ELEM_INT16 4
6514 #define DUK_HBUFOBJ_ELEM_UINT32 5
6515 #define DUK_HBUFOBJ_ELEM_INT32 6
6516 #define DUK_HBUFOBJ_ELEM_FLOAT32 7
6517 #define DUK_HBUFOBJ_ELEM_FLOAT64 8
6518 #define DUK_HBUFOBJ_ELEM_MAX 8
6519 
6520 #define DUK_ASSERT_HBUFOBJ_VALID(h) do { \
6521  DUK_ASSERT((h) != NULL); \
6522  DUK_ASSERT((h)->shift <= 3); \
6523  DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \
6524  DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \
6525  ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \
6526  ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \
6527  ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \
6528  ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \
6529  ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \
6530  ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \
6531  ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \
6532  ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \
6533  DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \
6534  DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \
6535  if ((h)->buf == NULL) { \
6536  DUK_ASSERT((h)->offset == 0); \
6537  DUK_ASSERT((h)->length == 0); \
6538  } else { \
6539  /* No assertions for offset or length; in particular, \
6540  * it's OK for length to be longer than underlying \
6541  * buffer. Just ensure they don't wrap when added. \
6542  */ \
6543  DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
6544  } \
6545  } while (0)
6546 
6547 /* Get the current data pointer (caller must ensure buf != NULL) as a
6548  * duk_uint8_t ptr.
6549  */
6550 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
6551  (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
6552  (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
6553 
6554 /* True if slice is full, i.e. offset is zero and length covers the entire
6555  * buffer. This status may change independently of the duk_hbufobj if
6556  * the underlying buffer is dynamic and changes without the hbufobj
6557  * being changed.
6558  */
6559 #define DUK_HBUFOBJ_FULL_SLICE(h) \
6560  (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
6561  ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
6562 
6563 /* Validate that the whole slice [0,length[ is contained in the underlying
6564  * buffer. Caller must ensure 'buf' != NULL.
6565  */
6566 #define DUK_HBUFOBJ_VALID_SLICE(h) \
6567  (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
6568  ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
6569 
6570 /* Validate byte read/write for virtual 'offset', i.e. check that the
6571  * offset, taking into account h->offset, is within the underlying
6572  * buffer size. This is a safety check which is needed to ensure
6573  * that even a misconfigured duk_hbufobj never causes memory unsafe
6574  * behavior (e.g. if an underlying dynamic buffer changes after being
6575  * setup). Caller must ensure 'buf' != NULL.
6576  */
6577 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
6578  (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
6579  ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
6580 
6581 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
6582  (DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
6583  ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
6584 
6585 /* Clamp an input byte length (already assumed to be within the nominal
6586  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
6587  * a byte length limit that's safe for memory accesses. This value can
6588  * be invalidated by any side effect because it may trigger a user
6589  * callback that resizes the underlying buffer.
6590  */
6591 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
6592  (DUK_ASSERT_EXPR((h) != NULL), \
6593  duk_hbufobj_clamp_bytelength((h), (len)))
6594 
6595 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
6596 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray)
6597 
6598 struct duk_hbufobj {
6599  /* Shared object part. */
6600  duk_hobject obj;
6601 
6602  /* Underlying buffer (refcounted), may be NULL. */
6603  duk_hbuffer *buf;
6604 
6605  /* .buffer reference to an ArrayBuffer, may be NULL. */
6606  duk_hobject *buf_prop;
6607 
6608  /* Slice and accessor information.
6609  *
6610  * Because the underlying buffer may be dynamic, these may be
6611  * invalidated by the buffer being modified so that both offset
6612  * and length should be validated before every access. Behavior
6613  * when the underlying buffer has changed doesn't need to be clean:
6614  * virtual 'length' doesn't need to be affected, reads can return
6615  * zero/NaN, and writes can be ignored.
6616  *
6617  * Note that a data pointer cannot be precomputed because 'buf' may
6618  * be dynamic and its pointer unstable.
6619  */
6620 
6621  duk_uint_t offset; /* byte offset to buf */
6622  duk_uint_t length; /* byte index limit for element access, exclusive */
6623  duk_uint8_t shift; /* element size shift:
6624  * 0 = u8/i8
6625  * 1 = u16/i16
6626  * 2 = u32/i32/float
6627  * 3 = double
6628  */
6629  duk_uint8_t elem_type; /* element type */
6630  duk_uint8_t is_typedarray;
6631 };
6632 
6633 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
6634 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
6635 DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_context *ctx, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
6636 DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_context *ctx, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);
6637 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_context *ctx, duk_idx_t idx);
6638 
6639 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
6640 #endif /* DUK_HBUFOBJ_H_INCLUDED */
6641 /* #include duk_hthread.h */
6642 /*
6643  * Heap thread object representation.
6644  *
6645  * duk_hthread is also the 'context' (duk_context) for exposed APIs
6646  * which mostly operate on the topmost frame of the value stack.
6647  */
6648 
6649 #if !defined(DUK_HTHREAD_H_INCLUDED)
6650 #define DUK_HTHREAD_H_INCLUDED
6651 
6652 /*
6653  * Stack constants
6654  */
6655 
6656 #define DUK_VALSTACK_GROW_STEP 128 /* roughly 1 kiB */
6657 #define DUK_VALSTACK_SHRINK_THRESHOLD 256 /* roughly 2 kiB */
6658 #define DUK_VALSTACK_SHRINK_SPARE 64 /* roughly 0.5 kiB */
6659 #define DUK_VALSTACK_INITIAL_SIZE 128 /* roughly 1.0 kiB -> but rounds up to DUK_VALSTACK_GROW_STEP in practice */
6660 #define DUK_VALSTACK_INTERNAL_EXTRA 64 /* internal extra elements assumed on function entry,
6661  * always added to user-defined 'extra' for e.g. the
6662  * duk_check_stack() call.
6663  */
6664 #define DUK_VALSTACK_API_ENTRY_MINIMUM DUK_API_ENTRY_STACK
6665  /* number of elements guaranteed to be user accessible
6666  * (in addition to call arguments) on Duktape/C function entry.
6667  */
6668 
6669 /* Note: DUK_VALSTACK_INITIAL_SIZE must be >= DUK_VALSTACK_API_ENTRY_MINIMUM
6670  * + DUK_VALSTACK_INTERNAL_EXTRA so that the initial stack conforms to spare
6671  * requirements.
6672  */
6673 
6674 #define DUK_VALSTACK_DEFAULT_MAX 1000000L
6675 
6676 #define DUK_CALLSTACK_GROW_STEP 8 /* roughly 256 bytes */
6677 #define DUK_CALLSTACK_SHRINK_THRESHOLD 16 /* roughly 512 bytes */
6678 #define DUK_CALLSTACK_SHRINK_SPARE 8 /* roughly 256 bytes */
6679 #define DUK_CALLSTACK_INITIAL_SIZE 8
6680 #define DUK_CALLSTACK_DEFAULT_MAX 10000L
6681 
6682 #define DUK_CATCHSTACK_GROW_STEP 4 /* roughly 64 bytes */
6683 #define DUK_CATCHSTACK_SHRINK_THRESHOLD 8 /* roughly 128 bytes */
6684 #define DUK_CATCHSTACK_SHRINK_SPARE 4 /* roughly 64 bytes */
6685 #define DUK_CATCHSTACK_INITIAL_SIZE 4
6686 #define DUK_CATCHSTACK_DEFAULT_MAX 10000L
6687 
6688 /*
6689  * Activation defines
6690  */
6691 
6692 #define DUK_ACT_FLAG_STRICT (1 << 0) /* function executes in strict mode */
6693 #define DUK_ACT_FLAG_TAILCALLED (1 << 1) /* activation has tail called one or more times */
6694 #define DUK_ACT_FLAG_CONSTRUCT (1 << 2) /* function executes as a constructor (called via "new") */
6695 #define DUK_ACT_FLAG_PREVENT_YIELD (1 << 3) /* activation prevents yield (native call or "new") */
6696 #define DUK_ACT_FLAG_DIRECT_EVAL (1 << 4) /* activation is a direct eval call */
6697 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE (1 << 5) /* activation has active breakpoint(s) */
6698 
6699 #define DUK_ACT_GET_FUNC(act) ((act)->func)
6700 
6701 /*
6702  * Flags for __FILE__ / __LINE__ registered into tracedata
6703  */
6704 
6705 #define DUK_TB_FLAG_NOBLAME_FILELINE (1 << 0) /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
6706 
6707 /*
6708  * Catcher defines
6709  */
6710 
6711 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
6712 #define DUK_CAT_TYPE_MASK 0x0000000fUL
6713 #define DUK_CAT_TYPE_BITS 4
6714 #define DUK_CAT_LABEL_MASK 0xffffff00UL
6715 #define DUK_CAT_LABEL_BITS 24
6716 #define DUK_CAT_LABEL_SHIFT 8
6717 
6718 #define DUK_CAT_FLAG_CATCH_ENABLED (1 << 4) /* catch part will catch */
6719 #define DUK_CAT_FLAG_FINALLY_ENABLED (1 << 5) /* finally part will catch */
6720 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED (1 << 6) /* request to create catch binding */
6721 #define DUK_CAT_FLAG_LEXENV_ACTIVE (1 << 7) /* catch or with binding is currently active */
6722 
6723 #define DUK_CAT_TYPE_UNKNOWN 0
6724 #define DUK_CAT_TYPE_TCF 1
6725 #define DUK_CAT_TYPE_LABEL 2
6726 
6727 #define DUK_CAT_GET_TYPE(c) ((c)->flags & DUK_CAT_TYPE_MASK)
6728 #define DUK_CAT_GET_LABEL(c) (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
6729 
6730 #define DUK_CAT_HAS_CATCH_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
6731 #define DUK_CAT_HAS_FINALLY_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
6732 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c) ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
6733 #define DUK_CAT_HAS_LEXENV_ACTIVE(c) ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
6734 
6735 #define DUK_CAT_SET_CATCH_ENABLED(c) do { \
6736  (c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
6737  } while (0)
6738 #define DUK_CAT_SET_FINALLY_ENABLED(c) do { \
6739  (c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
6740  } while (0)
6741 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c) do { \
6742  (c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6743  } while (0)
6744 #define DUK_CAT_SET_LEXENV_ACTIVE(c) do { \
6745  (c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
6746  } while (0)
6747 
6748 #define DUK_CAT_CLEAR_CATCH_ENABLED(c) do { \
6749  (c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
6750  } while (0)
6751 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c) do { \
6752  (c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
6753  } while (0)
6754 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c) do { \
6755  (c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
6756  } while (0)
6757 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c) do { \
6758  (c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
6759  } while (0)
6760 
6761 /*
6762  * Thread defines
6763  */
6764 
6765 #if defined(DUK_USE_ROM_STRINGS)
6766 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6767  ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
6768 #else /* DUK_USE_ROM_STRINGS */
6769 #if defined(DUK_USE_HEAPPTR16)
6770 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6771  ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
6772 #else
6773 #define DUK_HTHREAD_GET_STRING(thr,idx) \
6774  ((thr)->strs[(idx)])
6775 #endif
6776 #endif /* DUK_USE_ROM_STRINGS */
6777 
6778 #define DUK_HTHREAD_GET_CURRENT_ACTIVATION(thr) (&(thr)->callstack[(thr)->callstack_top - 1])
6779 
6780 /* values for the state field */
6781 #define DUK_HTHREAD_STATE_INACTIVE 1 /* thread not currently running */
6782 #define DUK_HTHREAD_STATE_RUNNING 2 /* thread currently running (only one at a time) */
6783 #define DUK_HTHREAD_STATE_RESUMED 3 /* thread resumed another thread (active but not running) */
6784 #define DUK_HTHREAD_STATE_YIELDED 4 /* thread has yielded */
6785 #define DUK_HTHREAD_STATE_TERMINATED 5 /* thread has terminated */
6786 
6787 /* Executor interrupt default interval when nothing else requires a
6788  * smaller value. The default interval must be small enough to allow
6789  * for reasonable execution timeout checking but large enough to keep
6790  * impact on execution performance low.
6791  */
6792 #if defined(DUK_USE_INTERRUPT_COUNTER)
6793 #define DUK_HTHREAD_INTCTR_DEFAULT (256L * 1024L)
6794 #endif
6795 
6796 /*
6797  * Assert context is valid: non-NULL pointer, fields look sane.
6798  *
6799  * This is used by public API call entrypoints to catch invalid 'ctx' pointers
6800  * as early as possible; invalid 'ctx' pointers cause very odd and difficult to
6801  * diagnose behavior so it's worth checking even when the check is not 100%.
6802  */
6803 
6804 #if defined(DUK_USE_PREFER_SIZE)
6805 #define DUK_ASSERT_CTX_VSSIZE(ctx) /*nop*/
6806 #else
6807 #define DUK_ASSERT_CTX_VSSIZE(ctx) \
6808  DUK_ASSERT((duk_size_t) (((duk_hthread *) (ctx))->valstack_end - ((duk_hthread *) (ctx))->valstack) == \
6809  ((duk_hthread *) (ctx))->valstack_size)
6810 #endif
6811 #define DUK_ASSERT_CTX_VALID(ctx) do { \
6812  DUK_ASSERT((ctx) != NULL); \
6813  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (ctx)) == DUK_HTYPE_OBJECT); \
6814  DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (ctx))); \
6815  DUK_ASSERT(((duk_hthread *) (ctx))->unused1 == 0); \
6816  DUK_ASSERT(((duk_hthread *) (ctx))->unused2 == 0); \
6817  DUK_ASSERT(((duk_hthread *) (ctx))->valstack != NULL); \
6818  DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack); \
6819  DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack); \
6820  DUK_ASSERT(((duk_hthread *) (ctx))->valstack_top >= ((duk_hthread *) (ctx))->valstack_bottom); \
6821  DUK_ASSERT(((duk_hthread *) (ctx))->valstack_end >= ((duk_hthread *) (ctx))->valstack_top); \
6822  DUK_ASSERT_CTX_VSSIZE((ctx)); \
6823  } while (0)
6824 
6825 /*
6826  * Assertion helpers.
6827  */
6828 
6829 #define DUK_ASSERT_STRIDX_VALID(val) \
6830  DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
6831 
6832 #define DUK_ASSERT_BIDX_VALID(val) \
6833  DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
6834 
6835 /*
6836  * Misc
6837  */
6838 
6839 /* Fast access to 'this' binding. Assumes there's a call in progress. */
6840 #define DUK_HTHREAD_THIS_PTR(thr) \
6841  (DUK_ASSERT_EXPR((thr) != NULL), \
6842  DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
6843  (thr)->valstack_bottom - 1)
6844 
6845 /*
6846  * Struct defines
6847  */
6848 
6849 /* XXX: for a memory-code tradeoff, remove 'func' and make it's access either a function
6850  * or a macro. This would make the activation 32 bytes long on 32-bit platforms again.
6851  */
6852 
6853 /* Note: it's nice if size is 2^N (at least for 32-bit platforms). */
6855  duk_tval tv_func; /* borrowed: full duk_tval for function being executed; for lightfuncs */
6856  duk_hobject *func; /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
6857  duk_hobject *var_env; /* current variable environment (may be NULL if delayed) */
6858  duk_hobject *lex_env; /* current lexical environment (may be NULL if delayed) */
6859 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
6860  /* Previous value of 'func' caller, restored when unwound. Only in use
6861  * when 'func' is non-strict.
6862  */
6863  duk_hobject *prev_caller;
6864 #endif
6865 
6866  duk_instr_t *curr_pc; /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
6867 #if defined(DUK_USE_DEBUGGER_SUPPORT)
6868  duk_uint32_t prev_line; /* needed for stepping */
6869 #endif
6870  duk_small_uint_t flags;
6871 
6872  /* idx_bottom and idx_retval are only used for book-keeping of
6873  * Ecmascript-initiated calls, to allow returning to an Ecmascript
6874  * function properly. They are duk_size_t to match the convention
6875  * that value stack sizes are duk_size_t and local frame indices
6876  * are duk_idx_t.
6877  */
6878 
6879  /* Bottom of valstack for this activation, used to reset
6880  * valstack_bottom on return; index is absolute. Note:
6881  * idx_top not needed because top is set to 'nregs' always
6882  * when returning to an Ecmascript activation.
6883  */
6884  duk_size_t idx_bottom;
6885 
6886  /* Return value when returning to this activation (points to caller
6887  * reg, not callee reg); index is absolute (only set if activation is
6888  * not topmost).
6889  *
6890  * Note: idx_bottom is always set, while idx_retval is only applicable
6891  * for activations below the topmost one. Currently idx_retval for
6892  * the topmost activation is considered garbage (and it not initialized
6893  * on entry or cleared on return; may contain previous or garbage
6894  * values).
6895  */
6896  duk_size_t idx_retval;
6897 
6898  /* Current 'this' binding is the value just below idx_bottom.
6899  * Previously, 'this' binding was handled with an index to the
6900  * (calling) valstack. This works for everything except tail
6901  * calls, which must not "cumulate" valstack temps.
6902  */
6903 };
6904 
6905 /* Note: it's nice if size is 2^N (not 4x4 = 16 bytes on 32 bit) */
6906 struct duk_catcher {
6907  duk_hstring *h_varname; /* borrowed reference to catch variable name (or NULL if none) */
6908  /* (reference is valid as long activation exists) */
6909  duk_instr_t *pc_base; /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
6910  duk_size_t callstack_index; /* callstack index of related activation */
6911  duk_size_t idx_base; /* idx_base and idx_base+1 get completion value and type */
6912  duk_uint32_t flags; /* type and control flags, label number */
6913 };
6914 
6915 struct duk_hthread {
6916  /* Shared object part */
6917  duk_hobject obj;
6918 
6919  /* Pointer to bytecode executor's 'curr_pc' variable. Used to copy
6920  * the current PC back into the topmost activation when activation
6921  * state is about to change (or "syncing" is otherwise needed). This
6922  * is rather awkward but important for performance, see execution.rst.
6923  */
6924  duk_instr_t **ptr_curr_pc;
6925 
6926  /* Backpointers. */
6927  duk_heap *heap;
6928 
6929  /* Current strictness flag: affects API calls. */
6930  duk_uint8_t strict;
6931 
6932  /* Thread state. */
6933  duk_uint8_t state;
6934  duk_uint8_t unused1;
6935  duk_uint8_t unused2;
6936 
6937  /* Sanity limits for stack sizes. */
6938  duk_size_t valstack_max;
6939  duk_size_t callstack_max;
6940  duk_size_t catchstack_max;
6941 
6942  /* XXX: Valstack, callstack, and catchstack are currently assumed
6943  * to have non-NULL pointers. Relaxing this would not lead to big
6944  * benefits (except perhaps for terminated threads).
6945  */
6946 
6947  /* Value stack: these are expressed as pointers for faster stack manipulation.
6948  * [valstack,valstack_top[ is GC-reachable, [valstack_top,valstack_end[ is
6949  * not GC-reachable but kept initialized as 'undefined'.
6950  */
6951  duk_tval *valstack; /* start of valstack allocation */
6952  duk_tval *valstack_end; /* end of valstack allocation (exclusive) */
6953  duk_tval *valstack_bottom; /* bottom of current frame */
6954  duk_tval *valstack_top; /* top of current frame (exclusive) */
6955 #if !defined(DUK_USE_PREFER_SIZE)
6956  duk_size_t valstack_size; /* cached: valstack_end - valstack (in entries, not bytes) */
6957 #endif
6958 
6959  /* Call stack. [0,callstack_top[ is GC reachable. */
6960  duk_activation *callstack;
6961  duk_size_t callstack_size; /* allocation size */
6962  duk_size_t callstack_top; /* next to use, highest used is top - 1 */
6963  duk_size_t callstack_preventcount; /* number of activation records in callstack preventing a yield */
6964 
6965  /* Catch stack. [0,catchstack_top[ is GC reachable. */
6966  duk_catcher *catchstack;
6967  duk_size_t catchstack_size; /* allocation size */
6968  duk_size_t catchstack_top; /* next to use, highest used is top - 1 */
6969 
6970  /* Yield/resume book-keeping. */
6971  duk_hthread *resumer; /* who resumed us (if any) */
6972 
6973  /* Current compiler state (if any), used for augmenting SyntaxErrors. */
6974  duk_compiler_ctx *compile_ctx;
6975 
6976 #if defined(DUK_USE_INTERRUPT_COUNTER)
6977  /* Interrupt counter for triggering a slow path check for execution
6978  * timeout, debugger interaction such as breakpoints, etc. The value
6979  * is valid for the current running thread, and both the init and
6980  * counter values are copied whenever a thread switch occurs. It's
6981  * important for the counter to be conveniently accessible for the
6982  * bytecode executor inner loop for performance reasons.
6983  */
6984  duk_int_t interrupt_counter; /* countdown state */
6985  duk_int_t interrupt_init; /* start value for current countdown */
6986 #endif
6987 
6988  /* Builtin-objects; may or may not be shared with other threads,
6989  * threads existing in different "compartments" will have different
6990  * built-ins. Must be stored on a per-thread basis because there
6991  * is no intermediate structure for a thread group / compartment.
6992  * This takes quite a lot of space, currently 43x4 = 172 bytes on
6993  * 32-bit platforms.
6994  *
6995  * In some cases the builtins array could be ROM based, but it's
6996  * sometimes edited (e.g. for sandboxing) so it's better to keep
6997  * this array in RAM.
6998  */
6999  duk_hobject *builtins[DUK_NUM_BUILTINS];
7000 
7001  /* Convenience copies from heap/vm for faster access. */
7002 #if defined(DUK_USE_ROM_STRINGS)
7003  /* No field needed when strings are in ROM. */
7004 #else
7005 #if defined(DUK_USE_HEAPPTR16)
7006  duk_uint16_t *strs16;
7007 #else
7008  duk_hstring **strs;
7009 #endif
7010 #endif
7011 };
7012 
7013 /*
7014  * Prototypes
7015  */
7016 
7017 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7018 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7019 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7020 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7021 
7022 DUK_INTERNAL_DECL void duk_hthread_callstack_grow(duk_hthread *thr);
7023 DUK_INTERNAL_DECL void duk_hthread_callstack_shrink_check(duk_hthread *thr);
7024 DUK_INTERNAL_DECL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top);
7025 DUK_INTERNAL_DECL void duk_hthread_catchstack_grow(duk_hthread *thr);
7026 DUK_INTERNAL_DECL void duk_hthread_catchstack_shrink_check(duk_hthread *thr);
7027 DUK_INTERNAL_DECL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top);
7028 
7029 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr);
7030 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
7031 DUK_INTERNAL_DECL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
7032 DUK_INTERNAL_DECL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud); /* indirect allocs */
7033 
7034 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7035 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
7036 #endif
7037 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
7038 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
7039 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
7040 
7041 #endif /* DUK_HTHREAD_H_INCLUDED */
7042 /* #include duk_harray.h */
7043 /*
7044  * Heap Array object representation. Used for actual Array instances.
7045  *
7046  * All objects with the exotic array behavior (which must coincide with having
7047  * internal class array) MUST be duk_harrays. No other object can be a
7048  * duk_harray. However, duk_harrays may not always have an array part.
7049  */
7050 
7051 #if !defined(DUK_HARRAY_H_INCLUDED)
7052 #define DUK_HARRAY_H_INCLUDED
7053 
7054 #define DUK_ASSERT_HARRAY_VALID(h) do { \
7055  DUK_ASSERT((h) != NULL); \
7056  DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \
7057  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \
7058  } while (0)
7059 
7060 #define DUK_HARRAY_LENGTH_WRITABLE(h) (!(h)->length_nonwritable)
7061 #define DUK_HARRAY_LENGTH_NONWRITABLE(h) ((h)->length_nonwritable)
7062 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h) do { (h)->length_nonwritable = 0; } while (0)
7063 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h) do { (h)->length_nonwritable = 1; } while (0)
7064 
7065 struct duk_harray {
7066  /* Shared object part. */
7067  duk_hobject obj;
7068 
7069  /* Array .length.
7070  *
7071  * At present Array .length may be smaller, equal, or even larger
7072  * than the allocated underlying array part. Fast path code must
7073  * always take this into account carefully.
7074  */
7075  duk_uint32_t length;
7076 
7077  /* Array .length property attributes. The property is always
7078  * non-enumerable and non-configurable. It's initially writable
7079  * but per Object.defineProperty() rules it can be made non-writable
7080  * even if it is non-configurable. Thus we need to track the
7081  * writability explicitly.
7082  *
7083  * XXX: this field to be eliminated and moved into duk_hobject
7084  * flags field to save space.
7085  */
7086  duk_bool_t length_nonwritable;
7087 };
7088 
7089 #endif /* DUK_HARRAY_H_INCLUDED */
7090 /* #include duk_hbuffer.h */
7091 /*
7092  * Heap buffer representation.
7093  *
7094  * Heap allocated user data buffer which is either:
7095  *
7096  * 1. A fixed size buffer (data follows header statically)
7097  * 2. A dynamic size buffer (data pointer follows header)
7098  *
7099  * The data pointer for a variable size buffer of zero size may be NULL.
7100  */
7101 
7102 #if !defined(DUK_HBUFFER_H_INCLUDED)
7103 #define DUK_HBUFFER_H_INCLUDED
7104 
7105 /*
7106  * Flags
7107  *
7108  * Fixed buffer: 0
7109  * Dynamic buffer: DUK_HBUFFER_FLAG_DYNAMIC
7110  * External buffer: DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
7111  */
7112 
7113 #define DUK_HBUFFER_FLAG_DYNAMIC DUK_HEAPHDR_USER_FLAG(0) /* buffer is behind a pointer, dynamic or external */
7114 #define DUK_HBUFFER_FLAG_EXTERNAL DUK_HEAPHDR_USER_FLAG(1) /* buffer pointer is to an externally allocated buffer */
7115 
7116 #define DUK_HBUFFER_HAS_DYNAMIC(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
7117 #define DUK_HBUFFER_HAS_EXTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
7118 
7119 #define DUK_HBUFFER_SET_DYNAMIC(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
7120 #define DUK_HBUFFER_SET_EXTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
7121 
7122 #define DUK_HBUFFER_CLEAR_DYNAMIC(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
7123 #define DUK_HBUFFER_CLEAR_EXTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
7124 
7125 /*
7126  * Misc defines
7127  */
7128 
7129 /* Impose a maximum buffer length for now. Restricted artificially to
7130  * ensure resize computations or adding a heap header length won't
7131  * overflow size_t and that a signed duk_int_t can hold a buffer
7132  * length. The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
7133  */
7134 
7135 #if defined(DUK_USE_BUFLEN16)
7136 #define DUK_HBUFFER_MAX_BYTELEN (0x0000ffffUL)
7137 #else
7138 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
7139  * 2*len + 2 fits in 32 bits.
7140  */
7141 #define DUK_HBUFFER_MAX_BYTELEN (0x7ffffffeUL)
7142 #endif
7143 
7144 /*
7145  * Field access
7146  */
7147 
7148 /* Get/set the current user visible size, without accounting for a dynamic
7149  * buffer's "spare" (= usable size).
7150  */
7151 #if defined(DUK_USE_BUFLEN16)
7152 /* size stored in duk_heaphdr unused flag bits */
7153 #define DUK_HBUFFER_GET_SIZE(x) ((x)->hdr.h_flags >> 16)
7154 #define DUK_HBUFFER_SET_SIZE(x,v) do { \
7155  duk_size_t duk__v; \
7156  duk__v = (v); \
7157  DUK_ASSERT(duk__v <= 0xffffUL); \
7158  (x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
7159  } while (0)
7160 #define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
7161  (x)->hdr.h_flags += ((dv) << 16); \
7162  } while (0)
7163 #define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
7164  (x)->hdr.h_flags -= ((dv) << 16); \
7165  } while (0)
7166 #else
7167 #define DUK_HBUFFER_GET_SIZE(x) (((duk_hbuffer *) (x))->size)
7168 #define DUK_HBUFFER_SET_SIZE(x,v) do { \
7169  ((duk_hbuffer *) (x))->size = (v); \
7170  } while (0)
7171 #define DUK_HBUFFER_ADD_SIZE(x,dv) do { \
7172  (x)->size += (dv); \
7173  } while (0)
7174 #define DUK_HBUFFER_SUB_SIZE(x,dv) do { \
7175  (x)->size -= (dv); \
7176  } while (0)
7177 #endif
7178 
7179 #define DUK_HBUFFER_FIXED_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
7180 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
7181 
7182 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
7183 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
7184 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv) DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
7185 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv) DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
7186 
7187 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
7188 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v) DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
7189 
7190 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x) ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))
7191 
7192 #if defined(DUK_USE_HEAPPTR16)
7193 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
7194  ((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
7195 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
7196  ((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7197  } while (0)
7198 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
7199  ((duk_heaphdr *) (x))->h_extra16 = 0; /* assume 0 <=> NULL */ \
7200  } while (0)
7201 #else
7202 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) ((x)->curr_alloc)
7203 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v) do { \
7204  (x)->curr_alloc = (void *) (v); \
7205  } while (0)
7206 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x) do { \
7207  (x)->curr_alloc = (void *) NULL; \
7208  } while (0)
7209 #endif
7210 
7211 /* No pointer compression because pointer is potentially outside of
7212  * Duktape heap.
7213  */
7214 #if defined(DUK_USE_HEAPPTR16)
7215 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
7216  ((void *) (x)->curr_alloc)
7217 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
7218  (x)->curr_alloc = (void *) (v); \
7219  } while (0)
7220 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
7221  (x)->curr_alloc = (void *) NULL; \
7222  } while (0)
7223 #else
7224 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
7225  ((void *) (x)->curr_alloc)
7226 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v) do { \
7227  (x)->curr_alloc = (void *) (v); \
7228  } while (0)
7229 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x) do { \
7230  (x)->curr_alloc = (void *) NULL; \
7231  } while (0)
7232 #endif
7233 
7234 /* Get a pointer to the current buffer contents (matching current allocation
7235  * size). May be NULL for zero size dynamic/external buffer.
7236  */
7237 #if defined(DUK_USE_HEAPPTR16)
7238 #define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
7239  DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
7240  ( \
7241  DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
7242  DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
7243  DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
7244  ) : \
7245  DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
7246  )
7247 #else
7248 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
7249  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
7250  */
7251 #define DUK_HBUFFER_GET_DATA_PTR(heap,x) ( \
7252  DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
7253  DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
7254  DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \
7255  )
7256 #endif
7257 
7258 /*
7259  * Structs
7260  */
7261 
7262 /* Shared prefix for all buffer types. */
7263 struct duk_hbuffer {
7264  duk_heaphdr hdr;
7265 
7266  /* It's not strictly necessary to track the current size, but
7267  * it is useful for writing robust native code.
7268  */
7269 
7270  /* Current size (not counting a dynamic buffer's "spare"). */
7271 #if defined(DUK_USE_BUFLEN16)
7272  /* Stored in duk_heaphdr unused flags. */
7273 #else
7274  duk_size_t size;
7275 #endif
7276 
7277  /*
7278  * Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
7279  * flag.
7280  *
7281  * If the flag is clear (the buffer is a fixed size one), the buffer
7282  * data follows the header directly, consisting of 'size' bytes.
7283  *
7284  * If the flag is set, the actual buffer is allocated separately, and
7285  * a few control fields follow the header. Specifically:
7286  *
7287  * - a "void *" pointing to the current allocation
7288  * - a duk_size_t indicating the full allocated size (always >= 'size')
7289  *
7290  * If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
7291  * by user code, so that Duktape won't be able to resize it and won't
7292  * free it. This allows buffers to point to e.g. an externally
7293  * allocated structure such as a frame buffer.
7294  *
7295  * Unlike strings, no terminator byte (NUL) is guaranteed after the
7296  * data. This would be convenient, but would pad aligned user buffers
7297  * unnecessarily upwards in size. For instance, if user code requested
7298  * a 64-byte dynamic buffer, 65 bytes would actually be allocated which
7299  * would then potentially round upwards to perhaps 68 or 72 bytes.
7300  */
7301 };
7302 
7303 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
7304  * struct size.
7305  */
7306 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
7307 #pragma pack(push, 8)
7308 #endif
7310  /* A union is used here as a portable struct size / alignment trick:
7311  * by adding a 32-bit or a 64-bit (unused) union member, the size of
7312  * the struct is effectively forced to be a multiple of 4 or 8 bytes
7313  * (respectively) without increasing the size of the struct unless
7314  * necessary.
7315  */
7316  union {
7317  struct {
7318  duk_heaphdr hdr;
7319 #if defined(DUK_USE_BUFLEN16)
7320  /* Stored in duk_heaphdr unused flags. */
7321 #else
7322  duk_size_t size;
7323 #endif
7324  } s;
7325 #if (DUK_USE_ALIGN_BY == 4)
7326  duk_uint32_t dummy_for_align4;
7327 #elif (DUK_USE_ALIGN_BY == 8)
7328  duk_double_t dummy_for_align8;
7329 #elif (DUK_USE_ALIGN_BY == 1)
7330  /* no extra padding */
7331 #else
7332 #error invalid DUK_USE_ALIGN_BY
7333 #endif
7334  } u;
7335 
7336  /*
7337  * Data follows the struct header. The struct size is padded by the
7338  * compiler based on the struct members. This guarantees that the
7339  * buffer data will be aligned-by-4 but not necessarily aligned-by-8.
7340  *
7341  * On platforms where alignment does not matter, the struct padding
7342  * could be removed (if there is any). On platforms where alignment
7343  * by 8 is required, the struct size must be forced to be a multiple
7344  * of 8 by some means. Without it, some user code may break, and also
7345  * Duktape itself breaks (e.g. the compiler stores duk_tvals in a
7346  * dynamic buffer).
7347  */
7348 }
7349 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
7350 __attribute__ ((aligned (8)))
7351 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
7352 __attribute__ ((aligned (8)))
7353 #endif
7354 ;
7355 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
7356 #pragma pack(pop)
7357 #endif
7358 
7359 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
7360  * heap allocation primitives. Also used for external buffers when low memory
7361  * options are not used.
7362  */
7364  duk_heaphdr hdr;
7365 
7366 #if defined(DUK_USE_BUFLEN16)
7367  /* Stored in duk_heaphdr unused flags. */
7368 #else
7369  duk_size_t size;
7370 #endif
7371 
7372 #if defined(DUK_USE_HEAPPTR16)
7373  /* Stored in duk_heaphdr h_extra16. */
7374 #else
7375  void *curr_alloc; /* may be NULL if alloc_size == 0 */
7376 #endif
7377 
7378  /*
7379  * Allocation size for 'curr_alloc' is alloc_size. There is no
7380  * automatic NUL terminator for buffers (see above for rationale).
7381  *
7382  * 'curr_alloc' is explicitly allocated with heap allocation
7383  * primitives and will thus always have alignment suitable for
7384  * e.g. duk_tval and an IEEE double.
7385  */
7386 };
7387 
7388 /* External buffer with 'curr_alloc' managed by user code and pointing to an
7389  * arbitrary address. When heap pointer compression is not used, this struct
7390  * has the same layout as duk_hbuffer_dynamic.
7391  */
7393  duk_heaphdr hdr;
7394 
7395 #if defined(DUK_USE_BUFLEN16)
7396  /* Stored in duk_heaphdr unused flags. */
7397 #else
7398  duk_size_t size;
7399 #endif
7400 
7401  /* Cannot be compressed as a heap pointer because may point to
7402  * an arbitrary address.
7403  */
7404  void *curr_alloc; /* may be NULL if alloc_size == 0 */
7405 };
7406 
7407 /*
7408  * Prototypes
7409  */
7410 
7411 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
7412 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud); /* indirect allocs */
7413 
7414 /* dynamic buffer ops */
7415 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
7416 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
7417 
7418 #endif /* DUK_HBUFFER_H_INCLUDED */
7419 /* #include duk_heap.h */
7420 /*
7421  * Heap structure.
7422  *
7423  * Heap contains allocated heap objects, interned strings, and built-in
7424  * strings for one or more threads.
7425  */
7426 
7427 #if !defined(DUK_HEAP_H_INCLUDED)
7428 #define DUK_HEAP_H_INCLUDED
7429 
7430 /* alloc function typedefs in duktape.h */
7431 
7432 /*
7433  * Heap flags
7434  */
7435 
7436 #define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING (1 << 0) /* mark-and-sweep is currently running */
7437 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1 << 1) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
7438 #define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING (1 << 2) /* refcount code is processing refzero list */
7439 #define DUK_HEAP_FLAG_ERRHANDLER_RUNNING (1 << 3) /* an error handler (user callback to augment/replace error) is running */
7440 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 4) /* executor interrupt running (used to avoid nested interrupts) */
7441 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 5) /* heap destruction ongoing, finalizer rescue no longer possible */
7442 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1 << 6) /* debugger is paused: talk with debug client until step/resume */
7443 
7444 #define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
7445 #define DUK__HEAP_SET_FLAGS(heap,bits) do { \
7446  (heap)->flags |= (bits); \
7447  } while (0)
7448 #define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \
7449  (heap)->flags &= ~(bits); \
7450  } while (0)
7451 
7452 #define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
7453 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
7454 #define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
7455 #define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
7456 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
7457 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
7458 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
7459 
7460 #define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
7461 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
7462 #define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
7463 #define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
7464 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
7465 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
7466 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
7467 
7468 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING)
7469 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
7470 #define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING)
7471 #define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING)
7472 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
7473 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
7474 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
7475 
7476 /*
7477  * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
7478  */
7479 
7480 #define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
7481 #define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
7482 #define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
7483 #define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
7484 #define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
7485 #define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
7486 #define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
7487 #define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
7488 
7489 /*
7490  * Mark-and-sweep flags
7491  *
7492  * These are separate from heap level flags now but could be merged.
7493  * The heap structure only contains a 'base mark-and-sweep flags'
7494  * field and the GC caller can impose further flags.
7495  */
7496 
7497 #define DUK_MS_FLAG_EMERGENCY (1 << 0) /* emergency mode: try extra hard */
7498 #define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE (1 << 1) /* don't resize stringtable (but may sweep it); needed during stringtable resize */
7499 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2) /* don't compact objects; needed during object property allocation resize */
7500 #define DUK_MS_FLAG_NO_FINALIZERS (1 << 3) /* don't run finalizers; leave finalizable objects in finalize_list for next round */
7501 #define DUK_MS_FLAG_SKIP_FINALIZERS (1 << 4) /* don't run finalizers; queue finalizable objects back to heap_allocated */
7502 
7503 /*
7504  * Thread switching
7505  *
7506  * To switch heap->curr_thread, use the macro below so that interrupt counters
7507  * get updated correctly. The macro allows a NULL target thread because that
7508  * happens e.g. in call handling.
7509  */
7510 
7511 #if defined(DUK_USE_INTERRUPT_COUNTER)
7512 #define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr))
7513 #else
7514 #define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \
7515  (heap)->curr_thread = (newthr); \
7516  } while (0)
7517 #endif
7518 
7519 /*
7520  * Other heap related defines
7521  */
7522 
7523 /* Mark-and-sweep interval is relative to combined count of objects and
7524  * strings kept in the heap during the latest mark-and-sweep pass.
7525  * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is
7526  * decreased by each (re)allocation attempt (regardless of size), and each
7527  * refzero processed object.
7528  *
7529  * 'SKIP' indicates how many (re)allocations to wait until a retry if
7530  * GC is skipped because there is no thread do it with yet (happens
7531  * only during init phases).
7532  */
7533 #if defined(DUK_USE_REFERENCE_COUNTING)
7534 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
7535 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
7536 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
7537 #else
7538 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
7539 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
7540 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
7541 #endif
7542 
7543 /* Stringcache is used for speeding up char-offset-to-byte-offset
7544  * translations for non-ASCII strings.
7545  */
7546 #define DUK_HEAP_STRCACHE_SIZE 4
7547 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
7548 
7549 /* helper to insert a (non-string) heap object into heap allocated list */
7550 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr))
7551 
7552 /*
7553  * Stringtable
7554  */
7555 
7556 /* initial stringtable size, must be prime and higher than DUK_UTIL_MIN_HASH_PRIME */
7557 #define DUK_STRTAB_INITIAL_SIZE 17
7558 
7559 /* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */
7560 #define DUK_STRTAB_DELETED_MARKER(heap) ((duk_hstring *) heap)
7561 
7562 /* resizing parameters */
7563 #define DUK_STRTAB_MIN_FREE_DIVISOR 4 /* load factor max 75% */
7564 #define DUK_STRTAB_MIN_USED_DIVISOR 4 /* load factor min 25% */
7565 #define DUK_STRTAB_GROW_ST_SIZE(n) ((n) + (n)) /* used entries + approx 100% -> reset load to 50% */
7566 
7567 #define DUK_STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */
7568 #define DUK_STRTAB_HIGHEST_32BIT_PRIME 0xfffffffbUL
7569 
7570 /* probe sequence (open addressing) */
7571 #define DUK_STRTAB_HASH_INITIAL(hash,h_size) ((hash) % (h_size))
7572 #define DUK_STRTAB_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash))
7573 
7574 /* fixed top level hashtable size (separate chaining) */
7575 #define DUK_STRTAB_CHAIN_SIZE DUK_USE_STRTAB_CHAIN_SIZE
7576 
7577 /*
7578  * Built-in strings
7579  */
7580 
7581 /* heap string indices are autogenerated in duk_strings.h */
7582 #if defined(DUK_USE_ROM_STRINGS)
7583 #define DUK_HEAP_GET_STRING(heap,idx) \
7584  ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7585 #else /* DUK_USE_ROM_STRINGS */
7586 #if defined(DUK_USE_HEAPPTR16)
7587 #define DUK_HEAP_GET_STRING(heap,idx) \
7588  ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
7589 #else
7590 #define DUK_HEAP_GET_STRING(heap,idx) \
7591  ((heap)->strs[(idx)])
7592 #endif
7593 #endif /* DUK_USE_ROM_STRINGS */
7594 
7595 /*
7596  * Raw memory calls: relative to heap, but no GC interaction
7597  */
7598 
7599 #define DUK_ALLOC_RAW(heap,size) \
7600  ((heap)->alloc_func((heap)->heap_udata, (size)))
7601 
7602 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
7603  ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
7604 
7605 #define DUK_FREE_RAW(heap,ptr) \
7606  ((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
7607 
7608 /*
7609  * Memory calls: relative to heap, GC interaction, but no error throwing.
7610  *
7611  * XXX: Currently a mark-and-sweep triggered by memory allocation will run
7612  * using the heap->heap_thread. This thread is also used for running
7613  * mark-and-sweep finalization; this is not ideal because it breaks the
7614  * isolation between multiple global environments.
7615  *
7616  * Notes:
7617  *
7618  * - DUK_FREE() is required to ignore NULL and any other possible return
7619  * value of a zero-sized alloc/realloc (same as ANSI C free()).
7620  *
7621  * - There is no DUK_REALLOC_ZEROED because we don't assume to know the
7622  * old size. Caller must zero the reallocated memory.
7623  *
7624  * - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
7625  * by an allocation failure might invalidate the original 'ptr', thus
7626  * causing a realloc retry to use an invalid pointer. Example: we're
7627  * reallocating the value stack and a finalizer resizes the same value
7628  * stack during mark-and-sweep. The indirect variant requests for the
7629  * current location of the pointer being reallocated using a callback
7630  * right before every realloc attempt; this circuitous approach is used
7631  * to avoid strict aliasing issues in a more straightforward indirect
7632  * pointer (void **) approach. Note: the pointer in the storage
7633  * location is read but is NOT updated; the caller must do that.
7634  */
7635 
7636 /* callback for indirect reallocs, request for current pointer */
7637 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
7638 
7639 #define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size))
7640 #define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size))
7641 #define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
7642 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
7643 #define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr))
7644 
7645 /*
7646  * Memory constants
7647  */
7648 
7649 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 5 /* Retry allocation after mark-and-sweep for this
7650  * many times. A single mark-and-sweep round is
7651  * not guaranteed to free all unreferenced memory
7652  * because of finalization (in fact, ANY number of
7653  * rounds is strictly not enough).
7654  */
7655 
7656 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 /* Starting from this round, use emergency mode
7657  * for mark-and-sweep.
7658  */
7659 
7660 /*
7661  * Debugger support
7662  */
7663 
7664 /* Maximum number of breakpoints. Only breakpoints that are set are
7665  * consulted so increasing this has no performance impact.
7666  */
7667 #define DUK_HEAP_MAX_BREAKPOINTS 16
7668 
7669 /* Opcode interval for a Date-based status/peek rate limit check. Only
7670  * relevant when debugger is attached. Requesting a timestamp may be a
7671  * slow operation on some platforms so this shouldn't be too low. On the
7672  * other hand a high value makes Duktape react to a pause request slowly.
7673  */
7674 #define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
7675 
7676 /* Milliseconds between status notify and transport peeks. */
7677 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
7678 
7679 /* Step types */
7680 #define DUK_STEP_TYPE_NONE 0
7681 #define DUK_STEP_TYPE_INTO 1
7682 #define DUK_STEP_TYPE_OVER 2
7683 #define DUK_STEP_TYPE_OUT 3
7684 
7686  duk_hstring *filename;
7687  duk_uint32_t line;
7688 };
7689 
7690 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7691 #define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL)
7692 #define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \
7693  (heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \
7694  (heap)->dbg_step_thread = NULL; \
7695  (heap)->dbg_step_csindex = 0; \
7696  (heap)->dbg_step_startline = 0; \
7697  } while (0)
7698 #define DUK_HEAP_SET_PAUSED(heap) do { \
7699  DUK_HEAP_SET_DEBUGGER_PAUSED(heap); \
7700  (heap)->dbg_state_dirty = 1; \
7701  DUK_HEAP_CLEAR_STEP_STATE((heap)); \
7702  } while (0)
7703 #define DUK_HEAP_CLEAR_PAUSED(heap) do { \
7704  DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap); \
7705  (heap)->dbg_state_dirty = 1; \
7706  DUK_HEAP_CLEAR_STEP_STATE((heap)); \
7707  } while (0)
7708 #define DUK_HEAP_IS_PAUSED(heap) (DUK_HEAP_HAS_DEBUGGER_PAUSED((heap)))
7709 #endif /* DUK_USE_DEBUGGER_SUPPORT */
7710 
7711 /*
7712  * String cache should ideally be at duk_hthread level, but that would
7713  * cause string finalization to slow down relative to the number of
7714  * threads; string finalization must check the string cache for "weak"
7715  * references to the string being finalized to avoid dead pointers.
7716  *
7717  * Thus, string caches are now at the heap level now.
7718  */
7719 
7721  duk_hstring *h;
7722  duk_uint32_t bidx;
7723  duk_uint32_t cidx;
7724 };
7725 
7726 /*
7727  * Longjmp state, contains the information needed to perform a longjmp.
7728  * Longjmp related values are written to value1, value2, and iserror.
7729  */
7730 
7731 struct duk_ljstate {
7732  duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */
7733  duk_small_uint_t type; /* longjmp type */
7734  duk_bool_t iserror; /* isError flag for yield */
7735  duk_tval value1; /* 1st related value (type specific) */
7736  duk_tval value2; /* 2nd related value (type specific) */
7737 };
7738 
7739 /*
7740  * Stringtable entry for fixed size stringtable
7741  */
7742 
7744 #if defined(DUK_USE_HEAPPTR16)
7745  /* A 16-bit listlen makes sense with 16-bit heap pointers: there
7746  * won't be space for 64k strings anyway.
7747  */
7748  duk_uint16_t listlen; /* if 0, 'str16' used, if > 0, 'strlist16' used */
7749  union {
7750  duk_uint16_t strlist16;
7751  duk_uint16_t str16;
7752  } u;
7753 #else
7754  duk_size_t listlen; /* if 0, 'str' used, if > 0, 'strlist' used */
7755  union {
7756  duk_hstring **strlist;
7757  duk_hstring *str;
7758  } u;
7759 #endif
7760 };
7761 
7762 /*
7763  * Main heap structure
7764  */
7765 
7766 struct duk_heap {
7767  duk_small_uint_t flags;
7768 
7769  /* Allocator functions. */
7770  duk_alloc_function alloc_func;
7771  duk_realloc_function realloc_func;
7772  duk_free_function free_func;
7773 
7774  /* Heap udata, used for allocator functions but also for other heap
7775  * level callbacks like fatal function, pointer compression, etc.
7776  */
7777  void *heap_udata;
7778 
7779  /* Precomputed pointers when using 16-bit heap pointer packing. */
7780 #if defined(DUK_USE_HEAPPTR16)
7781  duk_uint16_t heapptr_null16;
7782  duk_uint16_t heapptr_deleted16;
7783 #endif
7784 
7785  /* Fatal error handling, called e.g. when a longjmp() is needed but
7786  * lj.jmpbuf_ptr is NULL. fatal_func must never return; it's not
7787  * declared as "noreturn" because doing that for typedefs is a bit
7788  * challenging portability-wise.
7789  */
7790  duk_fatal_function fatal_func;
7791 
7792  /* allocated heap objects */
7793  duk_heaphdr *heap_allocated;
7794 
7795  /* work list for objects whose refcounts are zero but which have not been
7796  * "finalized"; avoids recursive C calls when refcounts go to zero in a
7797  * chain of objects.
7798  */
7799 #if defined(DUK_USE_REFERENCE_COUNTING)
7800  duk_heaphdr *refzero_list;
7801  duk_heaphdr *refzero_list_tail;
7802 #endif
7803 
7804  /* mark-and-sweep control */
7805 #if defined(DUK_USE_VOLUNTARY_GC)
7806  duk_int_t mark_and_sweep_trigger_counter;
7807 #endif
7808  duk_int_t mark_and_sweep_recursion_depth;
7809 
7810  /* mark-and-sweep flags automatically active (used for critical sections) */
7811  duk_small_uint_t mark_and_sweep_base_flags;
7812 
7813  /* work list for objects to be finalized (by mark-and-sweep) */
7814  duk_heaphdr *finalize_list;
7815 
7816  /* longjmp state */
7817  duk_ljstate lj;
7818 
7819  /* marker for detecting internal "double faults", see duk_error_throw.c */
7820  duk_bool_t handling_error;
7821 
7822  /* heap thread, used internally and for finalization */
7823  duk_hthread *heap_thread;
7824 
7825  /* current thread */
7826  duk_hthread *curr_thread; /* currently running thread */
7827 
7828  /* heap level "stash" object (e.g., various reachability roots) */
7829  duk_hobject *heap_object;
7830 
7831  /* duk_handle_call / duk_handle_safe_call recursion depth limiting */
7832  duk_int_t call_recursion_depth;
7833  duk_int_t call_recursion_limit;
7834 
7835  /* mix-in value for computing string hashes; should be reasonably unpredictable */
7836  duk_uint32_t hash_seed;
7837 
7838  /* rnd_state for duk_util_tinyrandom.c */
7839 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
7840 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
7841  duk_uint32_t rnd_state; /* State for Shamir's three-op algorithm */
7842 #else
7843  duk_uint64_t rnd_state[2]; /* State for xoroshiro128+ */
7844 #endif
7845 #endif
7846 
7847  /* counter for unique local symbol creation */
7848  /* XXX: When 64-bit types are available, it would be more efficient to
7849  * use a duk_uint64_t at least for incrementing but maybe also for
7850  * string formatting in the Symbol constructor.
7851  */
7852  duk_uint32_t sym_counter[2];
7853 
7854  /* For manual debugging: instruction count based on executor and
7855  * interrupt counter book-keeping. Inspect debug logs to see how
7856  * they match up.
7857  */
7858 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
7859  duk_int_t inst_count_exec;
7860  duk_int_t inst_count_interrupt;
7861 #endif
7862 
7863  /* debugger */
7864 
7865 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7866  /* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */
7867  duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */
7868  duk_debug_write_function dbg_write_cb; /* required */
7869  duk_debug_peek_function dbg_peek_cb;
7870  duk_debug_read_flush_function dbg_read_flush_cb;
7871  duk_debug_write_flush_function dbg_write_flush_cb;
7872  duk_debug_request_function dbg_request_cb;
7873  duk_debug_detached_function dbg_detached_cb;
7874  void *dbg_udata;
7875 
7876  /* debugger state, only relevant when attached */
7877  duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
7878  duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */
7879  duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
7880  duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */
7881  duk_small_uint_t dbg_step_type; /* step type: none, step into, step over, step out */
7882  duk_hthread *dbg_step_thread; /* borrowed; NULL if no step state (NULLed in unwind) */
7883  duk_size_t dbg_step_csindex; /* callstack index */
7884  duk_uint32_t dbg_step_startline; /* starting line number */
7885  duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */
7886  duk_small_uint_t dbg_breakpoint_count;
7887  duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */
7888  /* XXX: make active breakpoints actual copies instead of pointers? */
7889 
7890  /* These are for rate limiting Status notifications and transport peeking. */
7891  duk_uint32_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */
7892  duk_uint32_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */
7893  duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */
7894 
7895  /* Used to support single-byte stream lookahead. */
7896  duk_bool_t dbg_have_next_byte;
7897  duk_uint8_t dbg_next_byte;
7898 #endif
7899 
7900  /* string intern table (weak refs) */
7901 #if defined(DUK_USE_STRTAB_PROBE)
7902 #if defined(DUK_USE_HEAPPTR16)
7903  duk_uint16_t *strtable16;
7904 #else
7905  duk_hstring **strtable;
7906 #endif
7907  duk_uint32_t st_size; /* alloc size in elements */
7908  duk_uint32_t st_used; /* used elements (includes DELETED) */
7909 #endif
7910 
7911  /* XXX: static alloc is OK until separate chaining stringtable
7912  * resizing is implemented.
7913  */
7914 #if defined(DUK_USE_STRTAB_CHAIN)
7915  duk_strtab_entry strtable[DUK_STRTAB_CHAIN_SIZE];
7916 #endif
7917 
7918  /* string access cache (codepoint offset -> byte offset) for fast string
7919  * character looping; 'weak' reference which needs special handling in GC.
7920  */
7921  duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];
7922 
7923  /* built-in strings */
7924 #if defined(DUK_USE_ROM_STRINGS)
7925  /* No field needed when strings are in ROM. */
7926 #else
7927 #if defined(DUK_USE_HEAPPTR16)
7928  duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
7929 #else
7930  duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
7931 #endif
7932 #endif
7933 };
7934 
7935 /*
7936  * Prototypes
7937  */
7938 
7939 DUK_INTERNAL_DECL
7940 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
7941  duk_realloc_function realloc_func,
7942  duk_free_function free_func,
7943  void *heap_udata,
7944  duk_fatal_function fatal_func);
7945 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
7946 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
7947 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
7948 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
7949 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
7950 
7951 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
7952 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
7953 DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
7954 #endif
7955 #if defined(DUK_USE_INTERRUPT_COUNTER)
7956 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
7957 #endif
7958 
7959 #if 0 /*unused*/
7960 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7961 #endif
7962 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
7963 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
7964 #if 0 /*unused*/
7965 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val);
7966 #endif
7967 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val);
7968 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
7969 #if defined(DUK_USE_REFERENCE_COUNTING)
7970 DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h);
7971 #endif
7972 #if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
7973 DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap);
7974 #endif
7975 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap);
7976 #if defined(DUK_USE_DEBUG)
7977 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap);
7978 #endif
7979 
7980 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
7981 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
7982 
7983 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
7984 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
7985 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
7986 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
7987 #endif
7988 
7989 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
7990 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
7991 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
7992 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
7993 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
7994 
7995 #if defined(DUK_USE_REFERENCE_COUNTING)
7996 DUK_INTERNAL_DECL void duk_refzero_free_pending(duk_hthread *thr);
7997 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr);
7998 #if 0 /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
7999 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
8000 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
8001 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
8002 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
8003 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
8004 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
8005 #endif
8006 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
8007 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
8008 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
8009 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h); /* no 'norz' variant */
8010 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h); /* no 'norz' variant */
8011 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
8012 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
8013 #else
8014 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
8015 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
8016 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
8017 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
8018 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
8019 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
8020 #endif
8021 #else /* DUK_USE_REFERENCE_COUNTING */
8022 /* no refcounting */
8023 #endif /* DUK_USE_REFERENCE_COUNTING */
8024 
8025 DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
8026 
8027 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
8028 
8029 #endif /* DUK_HEAP_H_INCLUDED */
8030 /* #include duk_debugger.h */
8031 #if !defined(DUK_DEBUGGER_H_INCLUDED)
8032 #define DUK_DEBUGGER_H_INCLUDED
8033 
8034 /* Debugger protocol version is defined in the public API header. */
8035 
8036 /* Initial bytes for markers. */
8037 #define DUK_DBG_IB_EOM 0x00
8038 #define DUK_DBG_IB_REQUEST 0x01
8039 #define DUK_DBG_IB_REPLY 0x02
8040 #define DUK_DBG_IB_ERROR 0x03
8041 #define DUK_DBG_IB_NOTIFY 0x04
8042 
8043 /* Other initial bytes. */
8044 #define DUK_DBG_IB_INT4 0x10
8045 #define DUK_DBG_IB_STR4 0x11
8046 #define DUK_DBG_IB_STR2 0x12
8047 #define DUK_DBG_IB_BUF4 0x13
8048 #define DUK_DBG_IB_BUF2 0x14
8049 #define DUK_DBG_IB_UNUSED 0x15
8050 #define DUK_DBG_IB_UNDEFINED 0x16
8051 #define DUK_DBG_IB_NULL 0x17
8052 #define DUK_DBG_IB_TRUE 0x18
8053 #define DUK_DBG_IB_FALSE 0x19
8054 #define DUK_DBG_IB_NUMBER 0x1a
8055 #define DUK_DBG_IB_OBJECT 0x1b
8056 #define DUK_DBG_IB_POINTER 0x1c
8057 #define DUK_DBG_IB_LIGHTFUNC 0x1d
8058 #define DUK_DBG_IB_HEAPPTR 0x1e
8059 /* The short string/integer initial bytes starting from 0x60 don't have
8060  * defines now.
8061  */
8062 
8063 /* Error codes. */
8064 #define DUK_DBG_ERR_UNKNOWN 0x00
8065 #define DUK_DBG_ERR_UNSUPPORTED 0x01
8066 #define DUK_DBG_ERR_TOOMANY 0x02
8067 #define DUK_DBG_ERR_NOTFOUND 0x03
8068 #define DUK_DBG_ERR_APPLICATION 0x04
8069 
8070 /* Commands and notifys initiated by Duktape. */
8071 #define DUK_DBG_CMD_STATUS 0x01
8072 #define DUK_DBG_CMD_UNUSED_2 0x02 /* Duktape 1.x: print notify */
8073 #define DUK_DBG_CMD_UNUSED_3 0x03 /* Duktape 1.x: alert notify */
8074 #define DUK_DBG_CMD_UNUSED_4 0x04 /* Duktape 1.x: log notify */
8075 #define DUK_DBG_CMD_THROW 0x05
8076 #define DUK_DBG_CMD_DETACHING 0x06
8077 #define DUK_DBG_CMD_APPNOTIFY 0x07
8078 
8079 /* Commands initiated by debug client. */
8080 #define DUK_DBG_CMD_BASICINFO 0x10
8081 #define DUK_DBG_CMD_TRIGGERSTATUS 0x11
8082 #define DUK_DBG_CMD_PAUSE 0x12
8083 #define DUK_DBG_CMD_RESUME 0x13
8084 #define DUK_DBG_CMD_STEPINTO 0x14
8085 #define DUK_DBG_CMD_STEPOVER 0x15
8086 #define DUK_DBG_CMD_STEPOUT 0x16
8087 #define DUK_DBG_CMD_LISTBREAK 0x17
8088 #define DUK_DBG_CMD_ADDBREAK 0x18
8089 #define DUK_DBG_CMD_DELBREAK 0x19
8090 #define DUK_DBG_CMD_GETVAR 0x1a
8091 #define DUK_DBG_CMD_PUTVAR 0x1b
8092 #define DUK_DBG_CMD_GETCALLSTACK 0x1c
8093 #define DUK_DBG_CMD_GETLOCALS 0x1d
8094 #define DUK_DBG_CMD_EVAL 0x1e
8095 #define DUK_DBG_CMD_DETACH 0x1f
8096 #define DUK_DBG_CMD_DUMPHEAP 0x20
8097 #define DUK_DBG_CMD_GETBYTECODE 0x21
8098 #define DUK_DBG_CMD_APPREQUEST 0x22
8099 #define DUK_DBG_CMD_GETHEAPOBJINFO 0x23
8100 #define DUK_DBG_CMD_GETOBJPROPDESC 0x24
8101 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE 0x25
8102 
8103 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
8104  * The remaining flags are specific to the debugger.
8105  */
8106 #define DUK_DBG_PROPFLAG_SYMBOL (1 << 8)
8107 #define DUK_DBG_PROPFLAG_HIDDEN (1 << 9)
8108 
8109 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8110 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
8111 
8112 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
8113 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
8114 
8115 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
8116 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
8117 
8118 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
8119 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
8120 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
8121 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
8122 /* XXX: exposed duk_debug_read_pointer */
8123 /* XXX: exposed duk_debug_read_buffer */
8124 /* XXX: exposed duk_debug_read_hbuffer */
8125 #if 0
8126 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
8127 #endif
8128 #if defined(DUK_USE_DEBUGGER_INSPECT)
8129 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
8130 #endif
8131 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
8132 
8133 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
8134 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
8135 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
8136 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
8137 #if defined(DUK_USE_DEBUGGER_INSPECT)
8138 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
8139 #endif
8140 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
8141 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
8142 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
8143 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
8144 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
8145 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
8146 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
8147 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
8148 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
8149 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
8150 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
8151 #endif
8152 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
8153 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
8154 #if 0 /* unused */
8155 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
8156 #endif
8157 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
8158 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
8159 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
8160 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
8161 
8162 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
8163 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
8164 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
8165 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
8166 #endif
8167 
8168 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
8169 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
8170 
8171 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
8172 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
8173 #endif
8174 
8175 #endif /* DUK_DEBUGGER_H_INCLUDED */
8176 /* #include duk_debug.h */
8177 /*
8178  * Debugging macros, DUK_DPRINT() and its variants in particular.
8179  *
8180  * DUK_DPRINT() allows formatted debug prints, and supports standard
8181  * and Duktape specific formatters. See duk_debug_vsnprintf.c for details.
8182  *
8183  * DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
8184  * for technical reasons. They are concretely used to hide 'x' from the
8185  * compiler when the corresponding log level is disabled. This allows
8186  * clean builds on non-C99 compilers, at the cost of more verbose code.
8187  * Examples:
8188  *
8189  * DUK_D(DUK_DPRINT("foo"));
8190  * DUK_DD(DUK_DDPRINT("foo"));
8191  * DUK_DDD(DUK_DDDPRINT("foo"));
8192  *
8193  * This approach is preferable to the old "double parentheses" hack because
8194  * double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
8195  * no longer be added transparently without going through globals, which
8196  * works poorly with threading.
8197  */
8198 
8199 #if !defined(DUK_DEBUG_H_INCLUDED)
8200 #define DUK_DEBUG_H_INCLUDED
8201 
8202 #if defined(DUK_USE_DEBUG)
8203 
8204 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
8205 #define DUK_D(x) x
8206 #else
8207 #define DUK_D(x) do { } while (0) /* omit */
8208 #endif
8209 
8210 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
8211 #define DUK_DD(x) x
8212 #else
8213 #define DUK_DD(x) do { } while (0) /* omit */
8214 #endif
8215 
8216 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
8217 #define DUK_DDD(x) x
8218 #else
8219 #define DUK_DDD(x) do { } while (0) /* omit */
8220 #endif
8221 
8222 /*
8223  * Exposed debug macros: debugging enabled
8224  */
8225 
8226 #if defined(DUK_USE_VARIADIC_MACROS)
8227 
8228 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
8229  * possible compile time, but waste some space with shared function names.
8230  */
8231 #define DUK__DEBUG_LOG(lev,...) duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);
8232 
8233 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
8234 #define DUK_DPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
8235 #else
8236 #define DUK_DPRINT(...)
8237 #endif
8238 
8239 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
8240 #define DUK_DDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
8241 #else
8242 #define DUK_DDPRINT(...)
8243 #endif
8244 
8245 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
8246 #define DUK_DDDPRINT(...) DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
8247 #else
8248 #define DUK_DDDPRINT(...)
8249 #endif
8250 
8251 #else /* DUK_USE_VARIADIC_MACROS */
8252 
8253 #define DUK__DEBUG_STASH(lev) \
8254  (void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
8255  (void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
8256  (void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
8257  (void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
8258  (void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
8259  (void) (duk_debug_level_stash = (lev))
8260 
8261 /* Without variadic macros resort to comma expression trickery to handle debug
8262  * prints. This generates a lot of harmless warnings. These hacks are not
8263  * needed normally because DUK_D() and friends will hide the entire debug log
8264  * statement from the compiler.
8265  */
8266 
8267 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
8268 #define DUK_DPRINT DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log /* args go here in parens */
8269 #else
8270 #define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
8271 #endif
8272 
8273 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
8274 #define DUK_DDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log /* args go here in parens */
8275 #else
8276 #define DUK_DDPRINT 0 && /* args */
8277 #endif
8278 
8279 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
8280 #define DUK_DDDPRINT DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log /* args go here in parens */
8281 #else
8282 #define DUK_DDDPRINT 0 && /* args */
8283 #endif
8284 
8285 #endif /* DUK_USE_VARIADIC_MACROS */
8286 
8287 #else /* DUK_USE_DEBUG */
8288 
8289 /*
8290  * Exposed debug macros: debugging disabled
8291  */
8292 
8293 #define DUK_D(x) do { } while (0) /* omit */
8294 #define DUK_DD(x) do { } while (0) /* omit */
8295 #define DUK_DDD(x) do { } while (0) /* omit */
8296 
8297 #if defined(DUK_USE_VARIADIC_MACROS)
8298 
8299 #define DUK_DPRINT(...)
8300 #define DUK_DDPRINT(...)
8301 #define DUK_DDDPRINT(...)
8302 
8303 #else /* DUK_USE_VARIADIC_MACROS */
8304 
8305 #define DUK_DPRINT 0 && /* args go here as a comma expression in parens */
8306 #define DUK_DDPRINT 0 && /* args */
8307 #define DUK_DDDPRINT 0 && /* args */
8308 
8309 #endif /* DUK_USE_VARIADIC_MACROS */
8310 
8311 #endif /* DUK_USE_DEBUG */
8312 
8313 /*
8314  * Structs
8315  */
8316 
8317 #if defined(DUK_USE_DEBUG)
8318 struct duk_fixedbuffer {
8319  duk_uint8_t *buffer;
8320  duk_size_t length;
8321  duk_size_t offset;
8322  duk_bool_t truncated;
8323 };
8324 #endif
8325 
8326 /*
8327  * Prototypes
8328  */
8329 
8330 #if defined(DUK_USE_DEBUG)
8331 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
8332 #if 0 /*unused*/
8333 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
8334 #endif
8335 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
8336 
8337 #if defined(DUK_USE_VARIADIC_MACROS)
8338 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
8339 #else /* DUK_USE_VARIADIC_MACROS */
8340 /* parameter passing, not thread safe */
8341 #define DUK_DEBUG_STASH_SIZE 128
8342 #if !defined(DUK_SINGLE_FILE)
8343 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
8344 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
8345 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
8346 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
8347 #endif
8348 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
8349 #endif /* DUK_USE_VARIADIC_MACROS */
8350 
8351 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
8352 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
8353 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
8354 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
8355 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
8356 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
8357 
8358 #endif /* DUK_USE_DEBUG */
8359 
8360 #endif /* DUK_DEBUG_H_INCLUDED */
8361 /* #include duk_error.h */
8362 /*
8363  * Error handling macros, assertion macro, error codes.
8364  *
8365  * There are three types of 'errors':
8366  *
8367  * 1. Ordinary errors relative to a thread, cause a longjmp, catchable.
8368  * 2. Fatal errors relative to a heap, cause fatal handler to be called.
8369  * 3. Fatal errors without context, cause the default (not heap specific)
8370  * fatal handler to be called.
8371  *
8372  * Fatal errors without context are used by debug code such as assertions.
8373  * By providing a fatal error handler for a Duktape heap, user code can
8374  * avoid fatal errors without context in non-debug builds.
8375  */
8376 
8377 #if !defined(DUK_ERROR_H_INCLUDED)
8378 #define DUK_ERROR_H_INCLUDED
8379 
8380 /*
8381  * Error codes: defined in duktape.h
8382  *
8383  * Error codes are used as a shorthand to throw exceptions from inside
8384  * the implementation. The appropriate Ecmascript object is constructed
8385  * based on the code. Ecmascript code throws objects directly. The error
8386  * codes are defined in the public API header because they are also used
8387  * by calling code.
8388  */
8389 
8390 /*
8391  * Normal error
8392  *
8393  * Normal error is thrown with a longjmp() through the current setjmp()
8394  * catchpoint record in the duk_heap. The 'curr_thread' of the duk_heap
8395  * identifies the throwing thread.
8396  *
8397  * Error formatting is usually unnecessary. The error macros provide a
8398  * zero argument version (no formatting) and separate macros for small
8399  * argument counts. Variadic macros are not used to avoid portability
8400  * issues and avoid the need for stash-based workarounds when they're not
8401  * available. Vararg calls are avoided for non-formatted error calls
8402  * because vararg call sites are larger than normal, and there are a lot
8403  * of call sites with no formatting.
8404  *
8405  * Note that special formatting provided by debug macros is NOT available.
8406  *
8407  * The _RAW variants allow the caller to specify file and line. This makes
8408  * it easier to write checked calls which want to use the call site of the
8409  * checked function, not the error macro call inside the checked function.
8410  */
8411 
8412 #if defined(DUK_USE_VERBOSE_ERRORS)
8413 
8414 /* Because there are quite many call sites, pack error code (require at most
8415  * 8-bit) into a single argument.
8416  */
8417 #define DUK_ERROR(thr,err,msg) do { \
8418  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
8419  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8420  duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
8421  } while (0)
8422 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
8423  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
8424  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8425  duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
8426  } while (0)
8427 
8428 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
8429  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
8430  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8431  duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
8432  } while (0)
8433 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
8434  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
8435  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8436  duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
8437  } while (0)
8438 
8439 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
8440  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
8441  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8442  duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
8443  } while (0)
8444 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
8445  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
8446  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8447  duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
8448  } while (0)
8449 
8450 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
8451  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
8452  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8453  duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
8454  } while (0)
8455 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
8456  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
8457  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8458  duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
8459  } while (0)
8460 
8461 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
8462  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
8463  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8464  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)); \
8465  } while (0)
8466 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
8467  duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
8468  DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
8469  duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
8470  } while (0)
8471 
8472 #else /* DUK_USE_VERBOSE_ERRORS */
8473 
8474 #define DUK_ERROR(thr,err,msg) duk_err_handle_error((thr), (err))
8475 #define DUK_ERROR_RAW(thr,file,line,err,msg) duk_err_handle_error((thr), (err))
8476 
8477 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
8478 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
8479 
8480 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
8481 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
8482 
8483 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
8484 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
8485 
8486 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
8487 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
8488 
8489 #endif /* DUK_USE_VERBOSE_ERRORS */
8490 
8491 /*
8492  * Fatal error without context
8493  *
8494  * The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
8495  */
8496 
8497 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
8498  duk_default_fatal_handler(NULL, (msg))
8499 
8500 /*
8501  * Error throwing helpers
8502  *
8503  * The goal is to provide verbose and configurable error messages. Call
8504  * sites should be clean in source code and compile to a small footprint.
8505  * Small footprint is also useful for performance because small cold paths
8506  * reduce code cache pressure. Adding macros here only makes sense if there
8507  * are enough call sites to get concrete benefits.
8508  *
8509  * DUK_ERROR_xxx() macros are generic and can be used anywhere.
8510  *
8511  * DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
8512  * the "return DUK_RET_xxx;" shorthand is available for low memory targets.
8513  * The DUK_DCERROR_xxx() macros always either throw or perform a
8514  * 'return DUK_RET_xxx' from the calling function.
8515  */
8516 
8517 #if defined(DUK_USE_VERBOSE_ERRORS)
8518 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
8519  * summaries (paranoid, for some security sensitive environments), the paranoid
8520  * vs. non-paranoid distinction affects only a few specific errors.
8521  */
8522 #if defined(DUK_USE_PARANOID_ERRORS)
8523 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
8524  duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
8525  } while (0)
8526 #else /* DUK_USE_PARANOID_ERRORS */
8527 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
8528  duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
8529  } while (0)
8530 #endif /* DUK_USE_PARANOID_ERRORS */
8531 
8532 #define DUK_ERROR_INTERNAL(thr) do { \
8533  duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8534  } while (0)
8535 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
8536  duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8537  } while (0)
8538 #define DUK_ERROR_UNSUPPORTED(thr) do { \
8539  DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
8540  } while (0)
8541 #define DUK_ERROR_ERROR(thr,msg) do { \
8542  duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
8543  } while (0)
8544 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
8545  duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
8546  } while (0)
8547 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
8548  duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8549  } while (0)
8550 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
8551  DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
8552  } while (0)
8553 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
8554  DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
8555  return 0; \
8556  } while (0)
8557 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
8558  DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
8559  } while (0)
8560 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
8561  DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
8562  } while (0)
8563 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
8564  DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
8565  return 0; \
8566  } while (0)
8567 #define DUK_ERROR_RANGE(thr,msg) do { \
8568  duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
8569  } while (0)
8570 #define DUK_ERROR_EVAL(thr,msg) do { \
8571  DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
8572  } while (0)
8573 #define DUK_ERROR_REFERENCE(thr,msg) do { \
8574  DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
8575  } while (0)
8576 #define DUK_ERROR_SYNTAX(thr,msg) do { \
8577  DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
8578  } while (0)
8579 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
8580  duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8581  } while (0)
8582 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
8583  DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
8584  return 0; \
8585  } while (0)
8586 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
8587  duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8588  } while (0)
8589 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
8590  DUK_ERROR_TYPE_INVALID_STATE((thr)); \
8591  return 0; \
8592  } while (0)
8593 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
8594  duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
8595  } while (0)
8596 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
8597  DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
8598  } while (0)
8599 #define DUK_ERROR_TYPE(thr,msg) do { \
8600  DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
8601  } while (0)
8602 #define DUK_ERROR_URI(thr,msg) do { \
8603  DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
8604  } while (0)
8605 #else /* DUK_USE_VERBOSE_ERRORS */
8606 /* Non-verbose errors for low memory targets: no file, line, or message. */
8607 
8608 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
8609  duk_err_type((thr)); \
8610  } while (0)
8611 
8612 #define DUK_ERROR_INTERNAL(thr) do { \
8613  duk_err_error((thr)); \
8614  } while (0)
8615 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
8616  duk_err_error((thr)); \
8617  } while (0)
8618 #define DUK_ERROR_UNSUPPORTED(thr) do { \
8619  duk_err_error((thr)); \
8620  } while (0)
8621 #define DUK_ERROR_ERROR(thr,msg) do { \
8622  duk_err_error((thr)); \
8623  } while (0)
8624 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
8625  duk_err_range((thr)); \
8626  } while (0)
8627 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
8628  duk_err_range((thr)); \
8629  } while (0)
8630 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
8631  duk_err_range((thr)); \
8632  } while (0)
8633 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
8634  DUK_UNREF((thr)); \
8635  return DUK_RET_RANGE_ERROR; \
8636  } while (0)
8637 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
8638  duk_err_range((thr)); \
8639  } while (0)
8640 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
8641  duk_err_range((thr)); \
8642  } while (0)
8643 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
8644  DUK_UNREF((thr)); \
8645  return DUK_RET_RANGE_ERROR; \
8646  } while (0)
8647 #define DUK_ERROR_RANGE(thr,msg) do { \
8648  duk_err_range((thr)); \
8649  } while (0)
8650 #define DUK_ERROR_EVAL(thr,msg) do { \
8651  duk_err_eval((thr)); \
8652  } while (0)
8653 #define DUK_ERROR_REFERENCE(thr,msg) do { \
8654  duk_err_reference((thr)); \
8655  } while (0)
8656 #define DUK_ERROR_SYNTAX(thr,msg) do { \
8657  duk_err_syntax((thr)); \
8658  } while (0)
8659 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
8660  duk_err_type((thr)); \
8661  } while (0)
8662 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
8663  DUK_UNREF((thr)); \
8664  return DUK_RET_TYPE_ERROR; \
8665  } while (0)
8666 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
8667  duk_err_type((thr)); \
8668  } while (0)
8669 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
8670  duk_err_type((thr)); \
8671  } while (0)
8672 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
8673  duk_err_type((thr)); \
8674  } while (0)
8675 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
8676  DUK_UNREF((thr)); \
8677  return DUK_RET_TYPE_ERROR; \
8678  } while (0)
8679 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
8680  duk_err_type((thr)); \
8681  } while (0)
8682 #define DUK_ERROR_TYPE(thr,msg) do { \
8683  duk_err_type((thr)); \
8684  } while (0)
8685 #define DUK_ERROR_URI(thr,msg) do { \
8686  duk_err_uri((thr)); \
8687  } while (0)
8688 #endif /* DUK_USE_VERBOSE_ERRORS */
8689 
8690 /*
8691  * Assert macro: failure causes a fatal error.
8692  *
8693  * NOTE: since the assert macro doesn't take a heap/context argument, there's
8694  * no way to look up a heap/context specific fatal error handler which may have
8695  * been given by the application. Instead, assertion failures always use the
8696  * internal default fatal error handler; it can be replaced via duk_config.h
8697  * and then applies to all Duktape heaps.
8698  */
8699 
8700 #if defined(DUK_USE_ASSERTIONS)
8701 
8702 /* The message should be a compile time constant without formatting (less risk);
8703  * we don't care about assertion text size because they're not used in production
8704  * builds.
8705  */
8706 #define DUK_ASSERT(x) do { \
8707  if (!(x)) { \
8708  DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
8709  " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
8710  } \
8711  } while (0)
8712 
8713 /* Assertion compatible inside a comma expression, evaluates to void. */
8714 #define DUK_ASSERT_EXPR(x) \
8715  ((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
8716  " (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
8717 
8718 #else /* DUK_USE_ASSERTIONS */
8719 
8720 #define DUK_ASSERT(x) do { /* assertion omitted */ } while (0)
8721 
8722 #define DUK_ASSERT_EXPR(x) ((void) 0)
8723 
8724 #endif /* DUK_USE_ASSERTIONS */
8725 
8726 /* this variant is used when an assert would generate a compile warning by
8727  * being always true (e.g. >= 0 comparison for an unsigned value
8728  */
8729 #define DUK_ASSERT_DISABLE(x) do { /* assertion disabled */ } while (0)
8730 
8731 /*
8732  * Assertion helpers
8733  */
8734 
8735 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
8736 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) do { \
8737  DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
8738  } while (0)
8739 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) do { \
8740  if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
8741  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
8742  } \
8743  } while (0)
8744 #else
8745 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h) /* no refcount check */
8746 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv) /* no refcount check */
8747 #endif
8748 
8749 #define DUK_ASSERT_TOP(ctx,n) DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
8750 
8751 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
8752 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) do { \
8753  duk_double_union duk__assert_tmp_du; \
8754  duk__assert_tmp_du.d = (dval); \
8755  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
8756  } while (0)
8757 #else
8758 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval) /* nop */
8759 #endif
8760 
8761 #define DUK_ASSERT_VS_SPACE(thr) \
8762  DUK_ASSERT(thr->valstack_top < thr->valstack_end)
8763 
8764 /*
8765  * Helper for valstack space
8766  *
8767  * Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
8768  * required for its own use, and any child calls which are not (a) Duktape API calls
8769  * or (b) Duktape calls which involve extending the valstack (e.g. getter call).
8770  */
8771 
8772 #define DUK_VALSTACK_ASSERT_EXTRA 5 /* this is added to checks to allow for Duktape
8773  * API calls in addition to function's own use
8774  */
8775 #if defined(DUK_USE_ASSERTIONS)
8776 #define DUK_ASSERT_VALSTACK_SPACE(thr,n) do { \
8777  DUK_ASSERT((thr) != NULL); \
8778  DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
8779  } while (0)
8780 #else
8781 #define DUK_ASSERT_VALSTACK_SPACE(thr,n) /* no valstack space check */
8782 #endif
8783 
8784 /*
8785  * Prototypes
8786  */
8787 
8788 #if defined(DUK_USE_VERBOSE_ERRORS)
8789 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));
8790 DUK_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, ...));
8791 #else /* DUK_USE_VERBOSE_ERRORS */
8792 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
8793 #endif /* DUK_USE_VERBOSE_ERRORS */
8794 
8795 #if defined(DUK_USE_VERBOSE_ERRORS)
8796 DUK_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));
8797 #else
8798 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
8799 #endif
8800 
8801 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
8802 
8803 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
8804 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);
8805 #endif
8806 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
8807 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
8808 #endif
8809 
8810 #if defined(DUK_USE_VERBOSE_ERRORS)
8811 #if defined(DUK_USE_PARANOID_ERRORS)
8812 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
8813 #else
8814 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));
8815 #endif
8816 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8817 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8818 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8819 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
8820 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8821 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
8822 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8823 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8824 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
8825 #else /* DUK_VERBOSE_ERRORS */
8826 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
8827 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
8828 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
8829 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
8830 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
8831 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
8832 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
8833 #endif /* DUK_VERBOSE_ERRORS */
8834 
8835 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
8836 
8837 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
8838 
8839 DUK_INTERNAL_DECL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type);
8840 
8841 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
8842 
8843 #endif /* DUK_ERROR_H_INCLUDED */
8844 /* #include duk_unicode.h */
8845 /*
8846  * Unicode helpers
8847  */
8848 
8849 #if !defined(DUK_UNICODE_H_INCLUDED)
8850 #define DUK_UNICODE_H_INCLUDED
8851 
8852 /*
8853  * UTF-8 / XUTF-8 / CESU-8 constants
8854  */
8855 
8856 #define DUK_UNICODE_MAX_XUTF8_LENGTH 7 /* up to 36 bit codepoints */
8857 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8858 #define DUK_UNICODE_MAX_CESU8_LENGTH 6 /* all codepoints up to U+10FFFF */
8859 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH 3 /* all codepoints up to U+FFFF */
8860 
8861 /*
8862  * Useful Unicode codepoints
8863  *
8864  * Integer constants must be signed to avoid unexpected coercions
8865  * in comparisons.
8866  */
8867 
8868 #define DUK_UNICODE_CP_ZWNJ 0x200cL /* zero-width non-joiner */
8869 #define DUK_UNICODE_CP_ZWJ 0x200dL /* zero-width joiner */
8870 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER 0xfffdL /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
8871 
8872 /*
8873  * ASCII character constants
8874  *
8875  * C character literals like 'x' have a platform specific value and do
8876  * not match ASCII (UTF-8) values on e.g. EBCDIC platforms. So, use
8877  * these (admittedly awkward) constants instead. These constants must
8878  * also have signed values to avoid unexpected coercions in comparisons.
8879  *
8880  * http://en.wikipedia.org/wiki/ASCII
8881  */
8882 
8883 #define DUK_ASC_NUL 0x00
8884 #define DUK_ASC_SOH 0x01
8885 #define DUK_ASC_STX 0x02
8886 #define DUK_ASC_ETX 0x03
8887 #define DUK_ASC_EOT 0x04
8888 #define DUK_ASC_ENQ 0x05
8889 #define DUK_ASC_ACK 0x06
8890 #define DUK_ASC_BEL 0x07
8891 #define DUK_ASC_BS 0x08
8892 #define DUK_ASC_HT 0x09
8893 #define DUK_ASC_LF 0x0a
8894 #define DUK_ASC_VT 0x0b
8895 #define DUK_ASC_FF 0x0c
8896 #define DUK_ASC_CR 0x0d
8897 #define DUK_ASC_SO 0x0e
8898 #define DUK_ASC_SI 0x0f
8899 #define DUK_ASC_DLE 0x10
8900 #define DUK_ASC_DC1 0x11
8901 #define DUK_ASC_DC2 0x12
8902 #define DUK_ASC_DC3 0x13
8903 #define DUK_ASC_DC4 0x14
8904 #define DUK_ASC_NAK 0x15
8905 #define DUK_ASC_SYN 0x16
8906 #define DUK_ASC_ETB 0x17
8907 #define DUK_ASC_CAN 0x18
8908 #define DUK_ASC_EM 0x19
8909 #define DUK_ASC_SUB 0x1a
8910 #define DUK_ASC_ESC 0x1b
8911 #define DUK_ASC_FS 0x1c
8912 #define DUK_ASC_GS 0x1d
8913 #define DUK_ASC_RS 0x1e
8914 #define DUK_ASC_US 0x1f
8915 #define DUK_ASC_SPACE 0x20
8916 #define DUK_ASC_EXCLAMATION 0x21
8917 #define DUK_ASC_DOUBLEQUOTE 0x22
8918 #define DUK_ASC_HASH 0x23
8919 #define DUK_ASC_DOLLAR 0x24
8920 #define DUK_ASC_PERCENT 0x25
8921 #define DUK_ASC_AMP 0x26
8922 #define DUK_ASC_SINGLEQUOTE 0x27
8923 #define DUK_ASC_LPAREN 0x28
8924 #define DUK_ASC_RPAREN 0x29
8925 #define DUK_ASC_STAR 0x2a
8926 #define DUK_ASC_PLUS 0x2b
8927 #define DUK_ASC_COMMA 0x2c
8928 #define DUK_ASC_MINUS 0x2d
8929 #define DUK_ASC_PERIOD 0x2e
8930 #define DUK_ASC_SLASH 0x2f
8931 #define DUK_ASC_0 0x30
8932 #define DUK_ASC_1 0x31
8933 #define DUK_ASC_2 0x32
8934 #define DUK_ASC_3 0x33
8935 #define DUK_ASC_4 0x34
8936 #define DUK_ASC_5 0x35
8937 #define DUK_ASC_6 0x36
8938 #define DUK_ASC_7 0x37
8939 #define DUK_ASC_8 0x38
8940 #define DUK_ASC_9 0x39
8941 #define DUK_ASC_COLON 0x3a
8942 #define DUK_ASC_SEMICOLON 0x3b
8943 #define DUK_ASC_LANGLE 0x3c
8944 #define DUK_ASC_EQUALS 0x3d
8945 #define DUK_ASC_RANGLE 0x3e
8946 #define DUK_ASC_QUESTION 0x3f
8947 #define DUK_ASC_ATSIGN 0x40
8948 #define DUK_ASC_UC_A 0x41
8949 #define DUK_ASC_UC_B 0x42
8950 #define DUK_ASC_UC_C 0x43
8951 #define DUK_ASC_UC_D 0x44
8952 #define DUK_ASC_UC_E 0x45
8953 #define DUK_ASC_UC_F 0x46
8954 #define DUK_ASC_UC_G 0x47
8955 #define DUK_ASC_UC_H 0x48
8956 #define DUK_ASC_UC_I 0x49
8957 #define DUK_ASC_UC_J 0x4a
8958 #define DUK_ASC_UC_K 0x4b
8959 #define DUK_ASC_UC_L 0x4c
8960 #define DUK_ASC_UC_M 0x4d
8961 #define DUK_ASC_UC_N 0x4e
8962 #define DUK_ASC_UC_O 0x4f
8963 #define DUK_ASC_UC_P 0x50
8964 #define DUK_ASC_UC_Q 0x51
8965 #define DUK_ASC_UC_R 0x52
8966 #define DUK_ASC_UC_S 0x53
8967 #define DUK_ASC_UC_T 0x54
8968 #define DUK_ASC_UC_U 0x55
8969 #define DUK_ASC_UC_V 0x56
8970 #define DUK_ASC_UC_W 0x57
8971 #define DUK_ASC_UC_X 0x58
8972 #define DUK_ASC_UC_Y 0x59
8973 #define DUK_ASC_UC_Z 0x5a
8974 #define DUK_ASC_LBRACKET 0x5b
8975 #define DUK_ASC_BACKSLASH 0x5c
8976 #define DUK_ASC_RBRACKET 0x5d
8977 #define DUK_ASC_CARET 0x5e
8978 #define DUK_ASC_UNDERSCORE 0x5f
8979 #define DUK_ASC_GRAVE 0x60
8980 #define DUK_ASC_LC_A 0x61
8981 #define DUK_ASC_LC_B 0x62
8982 #define DUK_ASC_LC_C 0x63
8983 #define DUK_ASC_LC_D 0x64
8984 #define DUK_ASC_LC_E 0x65
8985 #define DUK_ASC_LC_F 0x66
8986 #define DUK_ASC_LC_G 0x67
8987 #define DUK_ASC_LC_H 0x68
8988 #define DUK_ASC_LC_I 0x69
8989 #define DUK_ASC_LC_J 0x6a
8990 #define DUK_ASC_LC_K 0x6b
8991 #define DUK_ASC_LC_L 0x6c
8992 #define DUK_ASC_LC_M 0x6d
8993 #define DUK_ASC_LC_N 0x6e
8994 #define DUK_ASC_LC_O 0x6f
8995 #define DUK_ASC_LC_P 0x70
8996 #define DUK_ASC_LC_Q 0x71
8997 #define DUK_ASC_LC_R 0x72
8998 #define DUK_ASC_LC_S 0x73
8999 #define DUK_ASC_LC_T 0x74
9000 #define DUK_ASC_LC_U 0x75
9001 #define DUK_ASC_LC_V 0x76
9002 #define DUK_ASC_LC_W 0x77
9003 #define DUK_ASC_LC_X 0x78
9004 #define DUK_ASC_LC_Y 0x79
9005 #define DUK_ASC_LC_Z 0x7a
9006 #define DUK_ASC_LCURLY 0x7b
9007 #define DUK_ASC_PIPE 0x7c
9008 #define DUK_ASC_RCURLY 0x7d
9009 #define DUK_ASC_TILDE 0x7e
9010 #define DUK_ASC_DEL 0x7f
9011 
9012 /*
9013  * Miscellaneous
9014  */
9015 
9016 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
9017  * to lowercase.
9018  */
9019 #define DUK_LOWERCASE_CHAR_ASCII(x) ((x) | 0x20)
9020 
9021 /*
9022  * Unicode tables
9023  */
9024 
9025 #if defined(DUK_USE_SOURCE_NONBMP)
9026 /*
9027  * Automatically generated by extract_chars.py, do not edit!
9028  */
9029 
9030 extern const duk_uint8_t duk_unicode_ids_noa[1036];
9031 #else
9032 /*
9033  * Automatically generated by extract_chars.py, do not edit!
9034  */
9035 
9036 extern const duk_uint8_t duk_unicode_ids_noabmp[625];
9037 #endif
9038 
9039 #if defined(DUK_USE_SOURCE_NONBMP)
9040 /*
9041  * Automatically generated by extract_chars.py, do not edit!
9042  */
9043 
9044 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
9045 #else
9046 /*
9047  * Automatically generated by extract_chars.py, do not edit!
9048  */
9049 
9050 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
9051 #endif
9052 
9053 #if defined(DUK_USE_SOURCE_NONBMP)
9054 /*
9055  * Automatically generated by extract_chars.py, do not edit!
9056  */
9057 
9058 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[530];
9059 #else
9060 /*
9061  * Automatically generated by extract_chars.py, do not edit!
9062  */
9063 
9064 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357];
9065 #endif
9066 
9067 /*
9068  * Automatically generated by extract_caseconv.py, do not edit!
9069  */
9070 
9071 extern const duk_uint8_t duk_unicode_caseconv_uc[1386];
9072 extern const duk_uint8_t duk_unicode_caseconv_lc[680];
9073 
9074 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
9075 /*
9076  * Automatically generated by extract_caseconv.py, do not edit!
9077  */
9078 
9079 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
9080 #endif
9081 
9082 /*
9083  * Extern
9084  */
9085 
9086 /* duk_unicode_support.c */
9087 #if !defined(DUK_SINGLE_FILE)
9088 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
9089 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
9090 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
9091 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
9092 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
9093 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
9094 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
9095 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
9096 #endif /* !DUK_SINGLE_FILE */
9097 
9098 /*
9099  * Prototypes
9100  */
9101 
9102 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
9103 #if defined(DUK_USE_ASSERTIONS)
9104 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
9105 #endif
9106 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
9107 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
9108 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);
9109 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);
9110 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
9111 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
9112 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
9113 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
9114 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
9115 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
9116 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
9117 #if defined(DUK_USE_REGEXP_SUPPORT)
9118 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
9119 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
9120 #endif
9121 
9122 #endif /* DUK_UNICODE_H_INCLUDED */
9123 /* #include duk_json.h */
9124 /*
9125  * Defines for JSON, especially duk_bi_json.c.
9126  */
9127 
9128 #if !defined(DUK_JSON_H_INCLUDED)
9129 #define DUK_JSON_H_INCLUDED
9130 
9131 /* Encoding/decoding flags */
9132 #define DUK_JSON_FLAG_ASCII_ONLY (1 << 0) /* escape any non-ASCII characters */
9133 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES (1 << 1) /* avoid key quotes when key is an ASCII Identifier */
9134 #define DUK_JSON_FLAG_EXT_CUSTOM (1 << 2) /* extended types: custom encoding */
9135 #define DUK_JSON_FLAG_EXT_COMPATIBLE (1 << 3) /* extended types: compatible encoding */
9136 
9137 /* How much stack to require on entry to object/array encode */
9138 #define DUK_JSON_ENC_REQSTACK 32
9139 
9140 /* How much stack to require on entry to object/array decode */
9141 #define DUK_JSON_DEC_REQSTACK 32
9142 
9143 /* How large a loop detection stack to use */
9144 #define DUK_JSON_ENC_LOOPARRAY 64
9145 
9146 /* Encoding state. Heap object references are all borrowed. */
9147 typedef struct {
9148  duk_hthread *thr;
9149  duk_bufwriter_ctx bw; /* output bufwriter */
9150  duk_hobject *h_replacer; /* replacer function */
9151  duk_hstring *h_gap; /* gap (if empty string, NULL) */
9152  duk_idx_t idx_proplist; /* explicit PropertyList */
9153  duk_idx_t idx_loop; /* valstack index of loop detection object */
9154  duk_small_uint_t flags;
9155  duk_small_uint_t flag_ascii_only;
9156  duk_small_uint_t flag_avoid_key_quotes;
9157 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
9158  duk_small_uint_t flag_ext_custom;
9159  duk_small_uint_t flag_ext_compatible;
9160  duk_small_uint_t flag_ext_custom_or_compatible;
9161 #endif
9162  duk_int_t recursion_depth;
9163  duk_int_t recursion_limit;
9164  duk_uint_t mask_for_undefined; /* type bit mask: types which certainly produce 'undefined' */
9165 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
9166  duk_small_uint_t stridx_custom_undefined;
9167  duk_small_uint_t stridx_custom_nan;
9168  duk_small_uint_t stridx_custom_neginf;
9169  duk_small_uint_t stridx_custom_posinf;
9170  duk_small_uint_t stridx_custom_function;
9171 #endif
9172  duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY]; /* indexed by recursion_depth */
9174 
9175 typedef struct {
9176  duk_hthread *thr;
9177  const duk_uint8_t *p;
9178  const duk_uint8_t *p_start;
9179  const duk_uint8_t *p_end;
9180  duk_idx_t idx_reviver;
9181  duk_small_uint_t flags;
9182 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
9183  duk_small_uint_t flag_ext_custom;
9184  duk_small_uint_t flag_ext_compatible;
9185  duk_small_uint_t flag_ext_custom_or_compatible;
9186 #endif
9187  duk_int_t recursion_depth;
9188  duk_int_t recursion_limit;
9190 
9191 #endif /* DUK_JSON_H_INCLUDED */
9192 /* #include duk_js.h */
9193 /*
9194  * Ecmascript execution, support primitives.
9195  */
9196 
9197 #if !defined(DUK_JS_H_INCLUDED)
9198 #define DUK_JS_H_INCLUDED
9199 
9200 /* Flags for call handling. */
9201 #define DUK_CALL_FLAG_IGNORE_RECLIMIT (1 << 0) /* duk_handle_call_xxx: call ignores C recursion limit (for errhandler calls) */
9202 #define DUK_CALL_FLAG_CONSTRUCTOR_CALL (1 << 1) /* duk_handle_call_xxx: constructor call (i.e. called as 'new Foo()') */
9203 #define DUK_CALL_FLAG_IS_RESUME (1 << 2) /* duk_handle_ecma_call_setup: setup for a resume() */
9204 #define DUK_CALL_FLAG_IS_TAILCALL (1 << 3) /* duk_handle_ecma_call_setup: setup for a tail call */
9205 #define DUK_CALL_FLAG_DIRECT_EVAL (1 << 4) /* call is a direct eval call */
9206 
9207 /* Flags for duk_js_equals_helper(). */
9208 #define DUK_EQUALS_FLAG_SAMEVALUE (1 << 0) /* use SameValue instead of non-strict equality */
9209 #define DUK_EQUALS_FLAG_STRICT (1 << 1) /* use strict equality instead of non-strict equality */
9210 
9211 /* Flags for duk_js_compare_helper(). */
9212 #define DUK_COMPARE_FLAG_NEGATE (1 << 0) /* negate result */
9213 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST (1 << 1) /* eval left argument first */
9214 
9215 /* conversions, coercions, comparison, etc */
9216 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
9217 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
9218 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
9219 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
9220 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
9221 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
9222 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
9223 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);
9224 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h);
9225 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);
9226 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);
9227 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
9228 #if 0 /* unused */
9229 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
9230 #endif
9231 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);
9232 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
9233 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
9234 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
9235 
9236 /* arithmetic */
9237 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
9238 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
9239 
9240 #define duk_js_equals(thr,tv_x,tv_y) \
9241  duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
9242 #define duk_js_strict_equals(tv_x,tv_y) \
9243  duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
9244 #define duk_js_samevalue(tv_x,tv_y) \
9245  duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
9246 
9247 /* E5 Sections 11.8.1, 11.8.5; x < y */
9248 #define duk_js_lessthan(thr,tv_x,tv_y) \
9249  duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
9250 
9251 /* E5 Sections 11.8.2, 11.8.5; x > y --> y < x */
9252 #define duk_js_greaterthan(thr,tv_x,tv_y) \
9253  duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
9254 
9255 /* E5 Sections 11.8.3, 11.8.5; x <= y --> not (x > y) --> not (y < x) */
9256 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
9257  duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
9258 
9259 /* E5 Sections 11.8.4, 11.8.5; x >= y --> not (x < y) */
9260 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
9261  duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
9262 
9263 /* identifiers and environment handling */
9264 #if 0 /*unused*/
9265 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
9266 #endif
9267 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
9268 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
9269 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
9270 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
9271 #if 0 /*unused*/
9272 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
9273 #endif
9274 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
9275 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);
9276 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
9277 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase);
9278 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t idx_bottom);
9279 DUK_INTERNAL_DECL
9280 void duk_js_push_closure(duk_hthread *thr,
9281  duk_hcompfunc *fun_temp,
9282  duk_hobject *outer_var_env,
9283  duk_hobject *outer_lex_env,
9284  duk_bool_t add_auto_proto);
9285 
9286 /* call handling */
9287 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);
9288 DUK_INTERNAL_DECL void duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t num_stack_args, duk_small_uint_t call_flags);
9289 DUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);
9290 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);
9291 
9292 /* bytecode execution */
9293 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
9294 
9295 #endif /* DUK_JS_H_INCLUDED */
9296 /* #include duk_numconv.h */
9297 /*
9298  * Number-to-string conversion. The semantics of these is very tightly
9299  * bound with the Ecmascript semantics required for call sites.
9300  */
9301 
9302 #if !defined(DUK_NUMCONV_H_INCLUDED)
9303 #define DUK_NUMCONV_H_INCLUDED
9304 
9305 /* Output a specified number of digits instead of using the shortest
9306  * form. Used for toPrecision() and toFixed().
9307  */
9308 #define DUK_N2S_FLAG_FIXED_FORMAT (1 << 0)
9309 
9310 /* Force exponential format. Used for toExponential(). */
9311 #define DUK_N2S_FLAG_FORCE_EXP (1 << 1)
9312 
9313 /* If number would need zero padding (for whole number part), use
9314  * exponential format instead. E.g. if input number is 12300, 3
9315  * digits are generated ("123"), output "1.23e+4" instead of "12300".
9316  * Used for toPrecision().
9317  */
9318 #define DUK_N2S_FLAG_NO_ZERO_PAD (1 << 2)
9319 
9320 /* Digit count indicates number of fractions (i.e. an absolute
9321  * digit index instead of a relative one). Used together with
9322  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
9323  */
9324 #define DUK_N2S_FLAG_FRACTION_DIGITS (1 << 3)
9325 
9326 /*
9327  * String-to-number conversion
9328  */
9329 
9330 /* Maximum exponent value when parsing numbers. This is not strictly
9331  * compliant as there should be no upper limit, but as we parse the
9332  * exponent without a bigint, impose some limit.
9333  */
9334 #define DUK_S2N_MAX_EXPONENT 1000000000
9335 
9336 /* Trim white space (= allow leading and trailing whitespace) */
9337 #define DUK_S2N_FLAG_TRIM_WHITE (1 << 0)
9338 
9339 /* Allow exponent */
9340 #define DUK_S2N_FLAG_ALLOW_EXP (1 << 1)
9341 
9342 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
9343 #define DUK_S2N_FLAG_ALLOW_GARBAGE (1 << 2)
9344 
9345 /* Allow leading plus sign */
9346 #define DUK_S2N_FLAG_ALLOW_PLUS (1 << 3)
9347 
9348 /* Allow leading minus sign */
9349 #define DUK_S2N_FLAG_ALLOW_MINUS (1 << 4)
9350 
9351 /* Allow 'Infinity' */
9352 #define DUK_S2N_FLAG_ALLOW_INF (1 << 5)
9353 
9354 /* Allow fraction part */
9355 #define DUK_S2N_FLAG_ALLOW_FRAC (1 << 6)
9356 
9357 /* Allow naked fraction (e.g. ".123") */
9358 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC (1 << 7)
9359 
9360 /* Allow empty fraction (e.g. "123.") */
9361 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC (1 << 8)
9362 
9363 /* Allow empty string to be interpreted as 0 */
9364 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO (1 << 9)
9365 
9366 /* Allow leading zeroes (e.g. "0123" -> "123") */
9367 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO (1 << 10)
9368 
9369 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
9370  * overrides radix argument and forces integer mode.
9371  */
9372 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT (1 << 11)
9373 
9374 /* Allow automatic detection of legacy octal base ("0n"),
9375  * overrides radix argument and forces integer mode.
9376  */
9377 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT (1 << 12)
9378 
9379 /* Allow automatic detection of ES2015 octal base ("0o123"),
9380  * overrides radix argument and forces integer mode.
9381  */
9382 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT (1 << 13)
9383 
9384 /* Allow automatic detection of ES2015 binary base ("0b10001"),
9385  * overrides radix argument and forces integer mode.
9386  */
9387 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT (1 << 14)
9388 
9389 /*
9390  * Prototypes
9391  */
9392 
9393 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);
9394 DUK_INTERNAL_DECL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags);
9395 
9396 #endif /* DUK_NUMCONV_H_INCLUDED */
9397 /* #include duk_bi_protos.h */
9398 /*
9399  * Prototypes for built-in functions not automatically covered by the
9400  * header declarations emitted by genbuiltins.py.
9401  */
9402 
9403 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
9404 #define DUK_BUILTIN_PROTOS_H_INCLUDED
9405 
9406 /* Buffer size needed for ISO 8601 formatting.
9407  * Accurate value is 32 + 1 for NUL termination:
9408  * >>> len('+123456-01-23T12:34:56.123+12:34')
9409  * 32
9410  * Include additional space to be safe.
9411  */
9412 #define DUK_BI_DATE_ISO8601_BUFSIZE 40
9413 
9414 /* Helpers exposed for internal use */
9415 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);
9416 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
9417 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
9418 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
9419 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
9420 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
9421 /* Built-in providers */
9422 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
9423 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx);
9424 #endif
9425 #if defined(DUK_USE_DATE_NOW_TIME)
9426 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(duk_context *ctx);
9427 #endif
9428 #if defined(DUK_USE_DATE_NOW_WINDOWS)
9429 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx);
9430 #endif
9431 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
9432 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
9433 #endif
9434 #if defined(DUK_USE_DATE_TZO_WINDOWS)
9435 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
9436 #endif
9437 #if defined(DUK_USE_DATE_PRS_STRPTIME)
9438 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str);
9439 #endif
9440 #if defined(DUK_USE_DATE_PRS_GETDATE)
9441 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str);
9442 #endif
9443 #if defined(DUK_USE_DATE_FMT_STRFTIME)
9444 DUK_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);
9445 #endif
9446 
9447 DUK_INTERNAL_DECL
9448 void duk_bi_json_parse_helper(duk_context *ctx,
9449  duk_idx_t idx_value,
9450  duk_idx_t idx_reviver,
9451  duk_small_uint_t flags);
9452 DUK_INTERNAL_DECL
9453 void duk_bi_json_stringify_helper(duk_context *ctx,
9454  duk_idx_t idx_value,
9455  duk_idx_t idx_replacer,
9456  duk_idx_t idx_space,
9457  duk_small_uint_t flags);
9458 
9459 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_context *ctx);
9460 
9461 #if defined(DUK_USE_ES6_PROXY)
9462 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_context *ctx, duk_hobject *h_proxy_target, duk_uint_t flags);
9463 #endif
9464 
9465 #endif /* DUK_BUILTIN_PROTOS_H_INCLUDED */
9466 /* #include duk_selftest.h */
9467 /*
9468  * Selftest code
9469  */
9470 
9471 #if !defined(DUK_SELFTEST_H_INCLUDED)
9472 #define DUK_SELFTEST_H_INCLUDED
9473 
9474 #if defined(DUK_USE_SELF_TESTS)
9475 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
9476  duk_realloc_function realloc_func,
9477  duk_free_function free_func,
9478  void *udata);
9479 #endif
9480 
9481 #endif /* DUK_SELFTEST_H_INCLUDED */
9482 
9483 #endif /* DUK_INTERNAL_H_INCLUDED */
9484 
9485 #if defined(DUK_USE_COMPUTED_NAN)
9486 DUK_INTERNAL double duk_computed_nan;
9487 #endif
9488 
9489 #if defined(DUK_USE_COMPUTED_INFINITY)
9490 DUK_INTERNAL double duk_computed_infinity;
9491 #endif
9492 
9493 #if defined(DUK_USE_REPL_FPCLASSIFY)
9494 DUK_INTERNAL int duk_repl_fpclassify(double x) {
9495  duk_double_union u;
9496  duk_uint_fast16_t expt;
9497  duk_small_int_t mzero;
9498 
9499  u.d = x;
9500  expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
9501  if (expt > 0x0000UL && expt < 0x7ff0UL) {
9502  /* expt values [0x001,0x7fe] = normal */
9503  return DUK_FP_NORMAL;
9504  }
9505 
9506  mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
9507  if (expt == 0x0000UL) {
9508  /* expt 0x000 is zero/subnormal */
9509  if (mzero) {
9510  return DUK_FP_ZERO;
9511  } else {
9512  return DUK_FP_SUBNORMAL;
9513  }
9514  } else {
9515  /* expt 0xfff is infinite/nan */
9516  if (mzero) {
9517  return DUK_FP_INFINITE;
9518  } else {
9519  return DUK_FP_NAN;
9520  }
9521  }
9522 }
9523 #endif
9524 
9525 #if defined(DUK_USE_REPL_SIGNBIT)
9526 DUK_INTERNAL int duk_repl_signbit(double x) {
9527  duk_double_union u;
9528  u.d = x;
9529  return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
9530 }
9531 #endif
9532 
9533 #if defined(DUK_USE_REPL_ISFINITE)
9534 DUK_INTERNAL int duk_repl_isfinite(double x) {
9535  int c = DUK_FPCLASSIFY(x);
9536  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
9537  return 0;
9538  } else {
9539  return 1;
9540  }
9541 }
9542 #endif
9543 
9544 #if defined(DUK_USE_REPL_ISNAN)
9545 DUK_INTERNAL int duk_repl_isnan(double x) {
9546  int c = DUK_FPCLASSIFY(x);
9547  return (c == DUK_FP_NAN);
9548 }
9549 #endif
9550 
9551 #if defined(DUK_USE_REPL_ISINF)
9552 DUK_INTERNAL int duk_repl_isinf(double x) {
9553  int c = DUK_FPCLASSIFY(x);
9554  return (c == DUK_FP_INFINITE);
9555 }
9556 #endif
9557 /*
9558  * Debugging macro calls.
9559  */
9560 
9561 /* #include duk_internal.h -> already included */
9562 
9563 #if defined(DUK_USE_DEBUG)
9564 
9565 /*
9566  * Debugging enabled
9567  */
9568 
9569 #include <stdio.h>
9570 #include <stdlib.h>
9571 #include <stdarg.h>
9572 
9573 #if !defined(DUK_USE_DEBUG_WRITE)
9574 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
9575 #endif
9576 
9577 #define DUK__DEBUG_BUFSIZE DUK_USE_DEBUG_BUFSIZE
9578 
9579 #if defined(DUK_USE_VARIADIC_MACROS)
9580 
9581 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
9582  va_list ap;
9583  long arg_level;
9584  const char *arg_file;
9585  long arg_line;
9586  const char *arg_func;
9587  const char *arg_msg;
9588  char buf[DUK__DEBUG_BUFSIZE];
9589 
9590  va_start(ap, fmt);
9591 
9592  DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
9593  duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
9594 
9595  arg_level = (long) level;
9596  arg_file = (const char *) file;
9597  arg_line = (long) line;
9598  arg_func = (const char *) func;
9599  arg_msg = (const char *) buf;
9600  DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
9601 
9602  va_end(ap);
9603 }
9604 
9605 #else /* DUK_USE_VARIADIC_MACROS */
9606 
9607 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9608 DUK_INTERNAL duk_int_t duk_debug_line_stash;
9609 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9610 DUK_INTERNAL duk_int_t duk_debug_level_stash;
9611 
9612 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
9613  va_list ap;
9614  long arg_level;
9615  const char *arg_file;
9616  long arg_line;
9617  const char *arg_func;
9618  const char *arg_msg;
9619  char buf[DUK__DEBUG_BUFSIZE];
9620 
9621  va_start(ap, fmt);
9622 
9623  DUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
9624  duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
9625 
9626  arg_level = (long) duk_debug_level_stash;
9627  arg_file = (const char *) duk_debug_file_stash;
9628  arg_line = (long) duk_debug_line_stash;
9629  arg_func = (const char *) duk_debug_func_stash;
9630  arg_msg = (const char *) buf;
9631  DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
9632 
9633  va_end(ap);
9634 }
9635 
9636 #endif /* DUK_USE_VARIADIC_MACROS */
9637 
9638 #else /* DUK_USE_DEBUG */
9639 
9640 /*
9641  * Debugging disabled
9642  */
9643 
9644 #endif /* DUK_USE_DEBUG */
9645 
9646 /* automatic undefs */
9647 #undef DUK__DEBUG_BUFSIZE
9648 /*
9649  * Automatically generated by genbuiltins.py, do not edit!
9650  */
9651 
9652 /* #include duk_internal.h -> already included */
9653 
9654 #if defined(DUK_USE_ROM_STRINGS)
9655 #error ROM support not enabled, rerun configure.py with --rom-support
9656 #else /* DUK_USE_ROM_STRINGS */
9657 DUK_INTERNAL const duk_uint8_t duk_strings_data[921] = {
9658 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
9659 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
9660 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
9661 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
9662 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
9663 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
9664 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
9665 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
9666 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
9667 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
9668 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
9669 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
9670 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
9671 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
9672 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
9673 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
9674 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
9675 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
9676 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
9677 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
9678 32,45,100,139,134,69,146,100,227,226,231,146,51,192,204,73,140,224,145,221,
9679 102,241,68,196,157,34,79,143,139,166,233,225,228,227,138,157,173,167,197,
9680 211,118,214,210,38,238,74,113,67,76,105,187,169,147,154,73,225,228,32,193,
9681 48,25,100,105,166,113,200,147,44,166,1,40,79,18,150,134,147,141,163,2,72,
9682 171,115,147,136,4,65,130,96,35,64,194,32,168,89,56,208,48,135,123,144,217,
9683 146,38,220,229,64,186,16,187,156,105,47,52,238,112,56,153,4,225,145,27,156,
9684 43,162,192,46,71,220,229,65,22,1,231,220,228,157,72,136,136,220,227,197,
9685 164,180,52,133,220,224,34,105,19,115,140,3,207,185,202,130,36,109,85,185,
9686 194,161,160,90,50,72,163,115,135,3,70,178,68,251,156,16,22,178,16,251,156,
9687 153,226,64,13,27,156,137,12,16,72,135,220,228,193,19,18,101,220,228,206,
9688 137,28,78,99,208,178,21,13,125,38,146,70,60,20,72,9,145,4,140,121,51,197,
9689 214,25,27,81,156,151,48,65,34,107,106,9,55,18,68,104,146,84,97,31,191,189,
9690 181,70,140,133,222,249,212,227,66,125,245,187,251,219,77,3,119,190,117,56,
9691 208,159,125,110,254,246,210,26,93,239,157,78,52,39,223,93,191,189,180,212,
9692 52,187,223,58,156,104,79,190,187,127,123,104,180,104,183,190,117,56,208,
9693 159,125,102,254,209,104,209,124,234,113,161,62,250,80,196,128,81,4,9,16,
9694 162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33,65,69,204,195,34,
9695 201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70,138,104,115,68,
9696 130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180,210,178,38,35,
9697 146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37,19,155,41,146,
9698 174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46,247,70,103,37,
9699 230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26,16,165,2,228,69,
9700 33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224,18,128,98,29,241,
9701 69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38,129,23,8,34,198,
9702 };
9703 #endif /* DUK_USE_ROM_STRINGS */
9704 
9705 #if defined(DUK_USE_ROM_OBJECTS)
9706 #error ROM support not enabled, rerun configure.py with --rom-support
9707 #else /* DUK_USE_ROM_OBJECTS */
9708 /* native functions: 164 */
9709 DUK_INTERNAL const duk_c_function duk_bi_native_functions[164] = {
9710  NULL,
9711  duk_bi_array_constructor,
9712  duk_bi_array_constructor_is_array,
9713  duk_bi_array_prototype_concat,
9714  duk_bi_array_prototype_indexof_shared,
9715  duk_bi_array_prototype_iter_shared,
9716  duk_bi_array_prototype_join_shared,
9717  duk_bi_array_prototype_pop,
9718  duk_bi_array_prototype_push,
9719  duk_bi_array_prototype_reduce_shared,
9720  duk_bi_array_prototype_reverse,
9721  duk_bi_array_prototype_shift,
9722  duk_bi_array_prototype_slice,
9723  duk_bi_array_prototype_sort,
9724  duk_bi_array_prototype_splice,
9725  duk_bi_array_prototype_to_string,
9726  duk_bi_array_prototype_unshift,
9727  duk_bi_arraybuffer_constructor,
9728  duk_bi_arraybuffer_isview,
9729  duk_bi_boolean_constructor,
9730  duk_bi_boolean_prototype_tostring_shared,
9731  duk_bi_buffer_compare_shared,
9732  duk_bi_buffer_readfield,
9733  duk_bi_buffer_slice_shared,
9734  duk_bi_buffer_writefield,
9735  duk_bi_dataview_constructor,
9736  duk_bi_date_constructor,
9737  duk_bi_date_constructor_now,
9738  duk_bi_date_constructor_parse,
9739  duk_bi_date_constructor_utc,
9740  duk_bi_date_prototype_get_shared,
9741  duk_bi_date_prototype_get_timezone_offset,
9742  duk_bi_date_prototype_set_shared,
9743  duk_bi_date_prototype_set_time,
9744  duk_bi_date_prototype_to_json,
9745  duk_bi_date_prototype_tostring_shared,
9746  duk_bi_date_prototype_value_of,
9747  duk_bi_duktape_object_act,
9748  duk_bi_duktape_object_compact,
9749  duk_bi_duktape_object_dec,
9750  duk_bi_duktape_object_enc,
9751  duk_bi_duktape_object_fin,
9752  duk_bi_duktape_object_gc,
9753  duk_bi_duktape_object_info,
9754  duk_bi_error_constructor_shared,
9755  duk_bi_error_prototype_filename_getter,
9756  duk_bi_error_prototype_filename_setter,
9757  duk_bi_error_prototype_linenumber_getter,
9758  duk_bi_error_prototype_linenumber_setter,
9759  duk_bi_error_prototype_stack_getter,
9760  duk_bi_error_prototype_stack_setter,
9761  duk_bi_error_prototype_to_string,
9762  duk_bi_function_constructor,
9763  duk_bi_function_prototype,
9764  duk_bi_function_prototype_apply,
9765  duk_bi_function_prototype_bind,
9766  duk_bi_function_prototype_call,
9767  duk_bi_function_prototype_to_string,
9768  duk_bi_global_object_decode_uri,
9769  duk_bi_global_object_decode_uri_component,
9770  duk_bi_global_object_encode_uri,
9771  duk_bi_global_object_encode_uri_component,
9772  duk_bi_global_object_escape,
9773  duk_bi_global_object_eval,
9774  duk_bi_global_object_is_finite,
9775  duk_bi_global_object_is_nan,
9776  duk_bi_global_object_parse_float,
9777  duk_bi_global_object_parse_int,
9778  duk_bi_global_object_unescape,
9779  duk_bi_json_object_parse,
9780  duk_bi_json_object_stringify,
9781  duk_bi_math_object_hypot,
9782  duk_bi_math_object_max,
9783  duk_bi_math_object_min,
9784  duk_bi_math_object_onearg_shared,
9785  duk_bi_math_object_random,
9786  duk_bi_math_object_twoarg_shared,
9787  duk_bi_nodejs_buffer_byte_length,
9788  duk_bi_nodejs_buffer_concat,
9789  duk_bi_nodejs_buffer_constructor,
9790  duk_bi_nodejs_buffer_copy,
9791  duk_bi_nodejs_buffer_fill,
9792  duk_bi_nodejs_buffer_is_buffer,
9793  duk_bi_nodejs_buffer_is_encoding,
9794  duk_bi_nodejs_buffer_tojson,
9795  duk_bi_nodejs_buffer_tostring,
9796  duk_bi_nodejs_buffer_write,
9797  duk_bi_number_constructor,
9798  duk_bi_number_prototype_to_exponential,
9799  duk_bi_number_prototype_to_fixed,
9800  duk_bi_number_prototype_to_locale_string,
9801  duk_bi_number_prototype_to_precision,
9802  duk_bi_number_prototype_to_string,
9803  duk_bi_number_prototype_value_of,
9804  duk_bi_object_constructor,
9805  duk_bi_object_constructor_assign,
9806  duk_bi_object_constructor_create,
9807  duk_bi_object_constructor_define_properties,
9808  duk_bi_object_constructor_define_property,
9809  duk_bi_object_constructor_get_own_property_descriptor,
9810  duk_bi_object_constructor_is,
9811  duk_bi_object_constructor_is_extensible,
9812  duk_bi_object_constructor_is_sealed_frozen_shared,
9813  duk_bi_object_constructor_keys_shared,
9814  duk_bi_object_constructor_prevent_extensions,
9815  duk_bi_object_constructor_seal_freeze_shared,
9816  duk_bi_object_getprototype_shared,
9817  duk_bi_object_prototype_has_own_property,
9818  duk_bi_object_prototype_is_prototype_of,
9819  duk_bi_object_prototype_property_is_enumerable,
9820  duk_bi_object_prototype_to_locale_string,
9821  duk_bi_object_prototype_to_string,
9822  duk_bi_object_prototype_value_of,
9823  duk_bi_object_setprototype_shared,
9824  duk_bi_pointer_constructor,
9825  duk_bi_pointer_prototype_tostring_shared,
9826  duk_bi_proxy_constructor,
9827  duk_bi_reflect_object_delete_property,
9828  duk_bi_reflect_object_get,
9829  duk_bi_reflect_object_has,
9830  duk_bi_reflect_object_set,
9831  duk_bi_regexp_constructor,
9832  duk_bi_regexp_prototype_exec,
9833  duk_bi_regexp_prototype_flags,
9834  duk_bi_regexp_prototype_shared_getter,
9835  duk_bi_regexp_prototype_test,
9836  duk_bi_regexp_prototype_tostring,
9837  duk_bi_string_constructor,
9838  duk_bi_string_constructor_from_char_code,
9839  duk_bi_string_constructor_from_code_point,
9840  duk_bi_string_prototype_caseconv_shared,
9841  duk_bi_string_prototype_char_at,
9842  duk_bi_string_prototype_char_code_at,
9843  duk_bi_string_prototype_concat,
9844  duk_bi_string_prototype_indexof_shared,
9845  duk_bi_string_prototype_locale_compare,
9846  duk_bi_string_prototype_match,
9847  duk_bi_string_prototype_repeat,
9848  duk_bi_string_prototype_replace,
9849  duk_bi_string_prototype_search,
9850  duk_bi_string_prototype_slice,
9851  duk_bi_string_prototype_split,
9852  duk_bi_string_prototype_substr,
9853  duk_bi_string_prototype_substring,
9854  duk_bi_string_prototype_to_string,
9855  duk_bi_string_prototype_trim,
9856  duk_bi_textdecoder_constructor,
9857  duk_bi_textdecoder_prototype_decode,
9858  duk_bi_textdecoder_prototype_shared_getter,
9859  duk_bi_textencoder_constructor,
9860  duk_bi_textencoder_prototype_encode,
9861  duk_bi_textencoder_prototype_encoding_getter,
9862  duk_bi_thread_constructor,
9863  duk_bi_thread_current,
9864  duk_bi_thread_resume,
9865  duk_bi_thread_yield,
9866  duk_bi_type_error_thrower,
9867  duk_bi_typedarray_buffer_getter,
9868  duk_bi_typedarray_bytelength_getter,
9869  duk_bi_typedarray_byteoffset_getter,
9870  duk_bi_typedarray_constructor,
9871  duk_bi_typedarray_set,
9872  duk_bi_uint8array_allocplain,
9873  duk_bi_uint8array_plainof,
9874 };
9875 #if defined(DUK_USE_DOUBLE_LE)
9876 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
9877 144,148,105,221,32,68,52,228,62,12,104,200,165,134,148,248,81,77,61,191,
9878 135,35,154,103,34,72,6,157,159,197,145,77,245,126,52,130,106,234,163,196,
9879 52,226,18,51,161,26,113,1,60,37,64,190,18,49,116,116,33,26,113,1,92,136,26,
9880 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
9881 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
9882 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
9883 147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
9884 116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
9885 15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
9886 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
9887 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
9888 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
9889 128,0,0,0,0,0,1,240,255,153,128,0,0,0,0,0,1,224,255,151,137,0,214,9,188,35,
9890 131,12,225,196,56,177,78,60,99,147,28,229,200,57,162,120,74,129,124,36,98,
9891 232,156,241,92,136,26,98,112,145,139,162,116,71,114,36,41,34,70,136,156,36,
9892 98,232,157,49,124,150,27,48,95,132,140,93,19,170,39,147,195,201,194,70,46,
9893 137,215,17,218,69,4,236,98,232,157,153,39,110,81,220,15,193,209,83,3,200,
9894 119,130,241,241,117,240,120,80,252,137,10,178,10,103,134,180,122,9,135,136,
9895 154,120,169,199,142,158,121,10,7,146,162,121,74,71,150,166,121,138,135,154,
9896 170,121,202,199,158,23,201,146,243,225,26,39,12,145,61,16,190,76,151,159,6,
9897 65,56,100,137,233,35,93,205,144,33,224,140,137,196,54,121,244,5,60,17,145,
9898 56,85,184,19,207,16,21,18,227,65,198,231,72,16,137,112,168,106,38,76,225,2,
9899 70,65,56,100,237,34,140,177,4,134,65,56,100,237,34,129,117,204,123,154,70,
9900 207,46,64,146,52,78,25,59,72,163,48,65,34,52,78,25,59,72,160,93,115,30,230,
9901 145,179,204,144,24,146,16,30,76,209,2,40,210,72,64,121,52,4,0,156,88,97,5,
9902 194,96,227,18,124,124,93,55,79,15,39,28,94,49,38,159,154,136,96,196,159,29,
9903 102,241,241,115,201,25,227,131,36,133,20,62,110,142,253,2,102,36,248,235,
9904 55,143,139,158,72,207,28,104,24,73,112,201,3,2,82,65,155,187,94,6,20,72,9,
9905 147,120,128,225,144,168,105,56,248,185,228,140,241,190,96,128,200,84,52,
9906 156,124,92,242,70,104,36,183,168,4,145,0,190,41,1,139,18,19,36,226,146,17,
9907 124,73,82,54,124,37,230,70,201,14,108,184,132,8,68,185,34,1,100,31,8,129,8,
9908 151,11,23,100,141,225,18,12,68,184,75,204,141,146,2,178,112,72,8,162,98,92,
9909 50,10,152,147,227,172,222,62,46,121,35,60,114,88,96,92,185,112,201,65,34,
9910 92,4,1,147,81,159,141,205,32,234,121,96,97,57,64,97,121,128,14,56,37,199,
9911 89,188,124,92,242,70,120,227,144,53,18,227,226,233,186,120,121,56,226,242,
9912 8,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,36,136,48,64,114,0,
9913 250,156,168,1,64,247,175,25,36,2,8,11,94,80,248,16,40,104,242,103,200,48,
9914 193,3,162,92,4,98,12,41,14,66,40,106,101,1,132,130,8,24,78,104,129,54,62,
9915 96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,178,
9916 58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,129,
9917 232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,201,
9918 126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,132,
9919 0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,46,
9920 36,29,4,78,69,6,60,226,31,192,7,255,252,24,160,163,11,23,51,130,56,35,193,
9921 56,100,238,31,6,150,46,103,4,225,147,143,114,27,62,233,241,200,137,182,133,
9922 42,142,167,216,6,23,216,0,97,28,17,224,39,223,32,80,142,8,240,78,25,56,9,
9923 248,8,22,39,12,156,123,144,217,240,19,240,18,6,19,154,32,79,194,124,14,134,
9924 140,151,227,139,226,52,11,88,37,62,33,163,37,248,226,248,141,32,213,184,64,
9925 89,56,39,49,224,137,60,100,5,96,38,35,249,8,15,18,61,96,17,60,200,6,145,1,
9926 17,31,206,64,89,45,2,39,161,0,178,122,209,63,74,2,101,64,202,113,67,77,235,
9927 64,92,221,197,186,196,143,4,9,19,188,1,25,187,139,112,128,178,113,110,177,
9928 35,193,2,68,239,0,46,110,229,30,242,71,130,4,137,222,4,35,55,113,110,16,22,
9929 78,81,239,36,120,32,72,157,224,64,147,138,25,237,0,52,72,242,2,126,82,3,74,
9930 129,148,227,234,66,12,112,28,140,155,104,203,169,158,9,133,158,4,25,36,1,
9931 61,96,47,181,80,46,132,129,255,255,255,255,255,255,222,254,39,172,67,118,
9932 170,5,208,144,0,64,0,0,0,0,0,0,51,16,0,0,0,0,0,0,62,31,200,245,238,146,38,
9933 138,147,105,13,42,26,137,226,0,0,0,0,0,0,7,131,249,30,180,134,4,209,82,109,
9934 33,165,67,81,60,64,0,0,0,0,0,0,240,255,28,144,155,104,0,0,0,0,0,0,0,0,16,
9935 117,59,130,48,155,98,48,187,144,3,205,220,42,46,65,237,72,27,55,112,151,
9936 123,154,70,205,0,94,208,129,115,119,31,18,9,18,67,155,183,34,12,176,96,175,
9937 4,100,74,228,3,237,38,43,31,192,109,117,171,0,228,164,219,72,0,0,0,0,0,0,
9938 248,127,196,234,111,0,50,110,224,193,50,114,83,138,26,107,192,131,38,238,
9939 77,12,39,37,56,161,166,188,11,132,188,12,74,110,226,220,32,44,156,24,38,78,
9940 74,113,67,77,120,28,148,221,197,184,64,89,57,52,48,156,148,226,134,154,240,
9941 64,195,94,8,56,123,193,11,85,116,140,45,240,3,152,147,228,208,194,95,0,89,
9942 137,62,22,139,95,48,64,70,200,67,28,98,79,180,152,139,218,45,124,193,1,27,
9943 33,16,65,137,62,49,205,153,236,132,81,102,36,251,73,137,157,115,102,123,33,
9944 24,57,137,62,12,19,37,144,142,40,196,159,105,49,15,160,153,44,132,128,198,
9945 36,248,48,98,200,73,18,98,79,180,152,135,208,98,200,74,16,98,79,135,117,35,
9946 43,33,44,89,137,62,210,98,63,93,72,202,200,76,20,98,79,140,67,105,50,74,
9947 200,77,26,98,79,180,152,153,212,54,147,36,172,132,225,70,36,249,34,9,205,
9948 28,172,132,241,166,36,251,73,138,93,32,156,209,202,200,80,30,98,79,140,66,
9949 214,137,16,78,104,229,100,40,146,49,39,218,76,76,234,22,180,72,130,115,71,
9950 43,33,72,137,137,62,77,12,38,92,210,113,197,44,137,59,64,7,145,39,201,161,
9951 132,184,64,249,18,124,98,22,180,72,130,115,71,43,101,76,148,137,62,210,98,
9952 103,80,181,162,68,19,154,57,91,42,130,164,73,242,68,19,154,57,91,95,84,108,
9953 137,62,210,98,151,72,39,52,114,182,190,176,169,18,124,98,27,73,146,86,223,
9954 215,27,34,79,180,152,153,212,54,147,36,173,191,176,34,68,159,14,234,70,86,
9955 231,217,23,34,79,180,152,143,215,82,50,183,62,208,121,18,124,24,38,75,101,
9956 108,84,137,62,210,98,31,65,50,91,43,130,36,73,241,142,108,207,109,125,209,
9957 114,36,251,73,137,157,115,102,123,107,239,11,145,39,194,209,107,230,8,8,
9958 219,127,124,116,137,62,210,98,47,104,181,243,4,4,109,191,192,135,49,39,204,
9959 16,17,178,24,32,242,36,249,130,2,54,203,7,6,104,14,76,131,140,144,0,0,0,0,
9960 0,0,0,1,141,207,215,12,78,126,193,46,190,126,192,98,179,246,4,197,231,236,
9961 10,193,9,114,11,172,64,73,146,83,236,145,169,237,1,6,120,14,78,129,179,40,
9962 249,18,149,175,207,141,199,27,76,248,156,81,177,207,139,198,9,169,199,129,
9963 58,136,19,202,11,179,20,240,149,2,248,72,197,209,200,148,162,117,48,39,148,
9964 151,102,42,228,64,211,19,132,140,93,28,137,74,39,85,2,121,81,118,98,238,68,
9965 133,36,72,209,19,132,140,93,28,137,74,39,87,2,121,89,118,98,190,75,13,152,
9966 47,194,70,46,142,68,165,19,172,129,60,176,187,49,79,39,135,147,132,140,93,
9967 28,137,74,39,91,2,121,105,118,98,142,210,40,39,99,23,71,34,82,135,8,128,
9968 120,72,13,42,226,145,97,87,224,168,1,58,182,232,232,64,22,85,181,187,177,
9969 107,2,64,7,213,183,74,7,121,207,215,242,17,119,49,248,94,173,198,210,36,15,
9970 232,34,182,84,113,95,115,240,221,91,141,163,160,72,1,220,164,194,175,121,
9971 123,103,224,186,244,64,24,45,68,84,251,33,9,64,15,217,66,51,209,218,210,
9972 129,154,118,254,205,61,65,204,126,23,178,132,103,165,3,52,237,253,154,122,
9973 131,216,252,167,224,121,44,48,46,95,203,166,238,74,113,67,77,201,128,219,
9974 152,164,82,6,0,203,76,64,64,9,210,211,18,4,4,144,221,49,40,64,76,13,211,19,
9975 5,4,192,221,45,66,1,4,24,207,76,82,2,8,136,94,152,156,24,157,45,49,64,6,75,
9976 191,76,80,66,149,110,116,116,197,8,41,240,247,79,70,188,6,183,27,76,80,194,
9977 45,198,210,211,20,144,171,113,180,116,52,197,40,27,1,125,34,240,27,16,221,
9978 42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
9979 33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
9980 183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
9981 140,144,230,192,0,0,0,0,0,136,211,64,182,120,43,135,126,16,68,52,174,195,
9982 144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
9983 32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
9984 35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
9985 236,224,175,131,117,2,178,112,145,139,163,145,131,114,70,46,142,218,27,182,
9986 72,197,209,219,56,26,53,161,166,32,128,56,18,2,129,239,94,50,76,130,68,230,
9987 202,113,160,167,146,94,163,134,66,161,164,227,226,231,146,51,198,249,147,
9988 71,209,67,73,210,94,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,
9989 155,163,191,68,28,98,79,143,139,166,233,225,228,227,139,198,37,210,244,208,
9990 24,137,112,151,153,27,36,5,100,224,146,105,184,100,196,95,18,84,141,159,9,
9991 121,145,178,67,155,46,33,38,187,168,252,211,243,81,92,2,14,40,16,50,37,202,
9992 160,150,154,67,152,148,20,28,76,156,89,26,105,158,63,232,16,44,150,129,18,
9993 146,44,28,96,14,98,216,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
9994 113,75,34,78,63,236,3,6,133,41,35,31,242,18,195,152,147,226,27,61,138,41,
9995 140,16,98,79,148,67,103,177,69,45,136,49,39,196,54,122,58,212,83,26,36,196,
9996 159,40,134,207,71,90,138,92,16,98,79,136,108,244,244,168,166,56,73,137,62,
9997 81,13,158,158,149,20,186,40,196,159,10,183,2,122,122,84,82,240,163,18,124,
9998 42,220,9,235,106,81,75,225,228,73,241,13,158,197,54,198,8,145,39,202,33,
9999 179,216,166,214,196,72,147,226,27,61,29,106,109,141,19,34,79,148,67,103,
10000 163,173,77,174,8,145,39,196,54,122,122,84,219,28,38,68,159,40,134,207,79,
10001 74,155,93,21,34,79,133,91,129,61,61,42,109,120,84,137,62,21,110,4,245,181,
10002 41,181,248,56,224,28,24,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
10003 113,75,34,78,63,236,3,6,133,41,35,31,242,11,174,254,160,34,84,8,35,16,98,
10004 146,38,55,32,33,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,0,0,0,0,30,
10005 7,230,56,199,161,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,0,0,0,0,
10006 30,7,230,55,36,33,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,0,0,0,0,
10007 30,7,234,40,11,91,133,199,172,8,111,248,128,239,88,16,222,56,191,242,49,
10008 198,69,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,
10009 49,185,65,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,
10010 63,49,198,77,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,
10011 240,63,49,185,97,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,
10012 0,0,64,49,198,85,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,
10013 0,0,64,49,185,129,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,
10014 0,0,0,64,49,198,93,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,
10015 0,0,0,64,49,185,161,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,
10016 0,0,0,16,64,49,198,101,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,
10017 0,0,0,0,16,64,49,185,193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,
10018 0,0,0,0,0,16,64,49,198,109,8,244,56,153,37,180,242,71,104,139,35,8,217,192,
10019 0,0,0,0,0,0,16,64,49,185,225,8,244,56,153,37,180,242,71,104,139,35,8,217,
10020 192,0,0,0,0,0,0,16,64,49,198,117,8,244,56,153,37,180,242,71,104,139,35,8,
10021 217,192,0,0,0,0,0,0,16,64,49,186,1,8,244,56,153,37,180,242,71,104,139,35,8,
10022 217,192,0,0,0,0,0,0,32,64,49,198,125,8,244,56,153,37,180,242,71,104,139,35,
10023 8,217,192,0,0,0,0,0,0,32,64,32,232,130,0,97,57,162,4,245,72,10,68,184,70,
10024 137,195,67,77,175,32,66,37,192,208,165,36,117,196,10,14,38,78,44,141,52,
10025 207,169,64,56,156,199,130,36,160,141,146,52,38,32,76,72,1,246,136,235,103,
10026 177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,171,37,
10027 20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,158,142,
10028 183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,246,136,
10029 235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,37,20,
10030 138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,75,161,
10031 37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,39,208,
10032 146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,129,89,
10033 58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,17,214,
10034 207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,207,
10035 161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,207,
10036 98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,78,
10037 209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,146,
10038 155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,104,
10039 142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,146,
10040 155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,217,
10041 233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,162,
10042 137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,77,
10043 156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,117,
10044 179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,162,
10045 100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,59,22,
10046 53,91,0,2,21,11,94,181,128,196,133,0,185,80,32,56,156,199,130,36,160,72,16,
10047 78,126,53,144,5,146,208,34,82,72,1,109,20,76,155,40,32,233,0,115,70,130,8,
10048 209,56,104,105,187,252,193,3,17,162,112,201,242,18,65,211,0,230,149,132,17,
10049 162,112,208,211,119,248,0,82,130,96,95,127,128,130,80,102,186,36,232,92,
10050 206,255,1,80,48,200,39,12,158,241,64,
10051 };
10052 #elif defined(DUK_USE_DOUBLE_BE)
10053 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
10054 144,148,105,221,32,68,52,228,62,12,104,200,165,134,148,248,81,77,61,191,
10055 135,35,154,103,34,72,6,157,159,197,145,77,245,126,52,130,106,234,163,196,
10056 52,226,18,51,161,26,113,1,60,37,64,190,18,49,116,116,33,26,113,1,92,136,26,
10057 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
10058 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
10059 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
10060 147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
10061 116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
10062 15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
10063 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
10064 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
10065 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
10066 128,255,240,0,0,0,0,0,1,153,128,255,224,0,0,0,0,0,1,151,137,0,214,9,188,35,
10067 131,12,225,196,56,177,78,60,99,147,28,229,200,57,162,120,74,129,124,36,98,
10068 232,156,241,92,136,26,98,112,145,139,162,116,71,114,36,41,34,70,136,156,36,
10069 98,232,157,49,124,150,27,48,95,132,140,93,19,170,39,147,195,201,194,70,46,
10070 137,215,17,218,69,4,236,98,232,157,153,39,110,81,220,15,193,209,83,3,200,
10071 119,130,241,241,117,240,120,80,252,137,10,178,10,103,134,180,122,9,135,136,
10072 154,120,169,199,142,158,121,10,7,146,162,121,74,71,150,166,121,138,135,154,
10073 170,121,202,199,158,23,201,146,243,225,26,39,12,145,61,16,190,76,151,159,6,
10074 65,56,100,137,233,35,93,205,144,33,224,140,137,196,54,121,244,5,60,17,145,
10075 56,85,184,19,207,16,21,18,227,65,198,231,72,16,137,112,168,106,38,76,225,2,
10076 70,65,56,100,237,34,140,177,4,134,65,56,100,237,34,129,117,204,123,154,70,
10077 207,46,64,146,52,78,25,59,72,163,48,65,34,52,78,25,59,72,160,93,115,30,230,
10078 145,179,204,144,24,146,16,30,76,209,2,40,210,72,64,121,52,4,0,156,88,97,5,
10079 194,96,227,18,124,124,93,55,79,15,39,28,94,49,38,159,154,136,96,196,159,29,
10080 102,241,241,115,201,25,227,131,36,133,20,62,110,142,253,2,102,36,248,235,
10081 55,143,139,158,72,207,28,104,24,73,112,201,3,2,82,65,155,187,94,6,20,72,9,
10082 147,120,128,225,144,168,105,56,248,185,228,140,241,190,96,128,200,84,52,
10083 156,124,92,242,70,104,36,183,168,4,145,0,190,41,1,139,18,19,36,226,146,17,
10084 124,73,82,54,124,37,230,70,201,14,108,184,132,8,68,185,34,1,100,31,8,129,8,
10085 151,11,23,100,141,225,18,12,68,184,75,204,141,146,2,178,112,72,8,162,98,92,
10086 50,10,152,147,227,172,222,62,46,121,35,60,114,88,96,92,185,112,201,65,34,
10087 92,4,1,147,81,159,141,205,32,234,121,96,97,57,64,97,121,128,14,56,37,199,
10088 89,188,124,92,242,70,120,227,144,53,18,227,226,233,186,120,121,56,226,242,
10089 8,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,36,136,48,64,114,0,
10090 250,156,168,1,64,247,175,25,36,2,8,11,94,80,248,16,40,104,242,103,200,48,
10091 193,3,162,92,4,98,12,41,14,66,40,106,101,1,132,130,8,24,78,104,129,54,62,
10092 96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,178,
10093 58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,129,
10094 232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,201,
10095 126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,132,
10096 0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,46,
10097 36,29,4,78,69,6,60,226,31,192,7,255,252,24,160,163,11,23,51,130,56,35,193,
10098 56,100,238,31,6,150,46,103,4,225,147,143,114,27,62,233,241,200,137,182,133,
10099 42,142,167,216,6,23,216,0,97,28,17,224,39,223,32,80,142,8,240,78,25,56,9,
10100 248,8,22,39,12,156,123,144,217,240,19,240,18,6,19,154,32,79,194,124,14,134,
10101 140,151,227,139,226,52,11,88,37,62,33,163,37,248,226,248,141,32,213,184,64,
10102 89,56,39,49,224,137,60,100,5,96,38,35,249,8,15,18,61,96,17,60,200,6,145,1,
10103 17,31,206,64,89,45,2,39,161,0,178,122,209,63,74,2,101,64,202,113,67,77,235,
10104 64,92,221,197,186,196,143,4,9,19,188,1,25,187,139,112,128,178,113,110,177,
10105 35,193,2,68,239,0,46,110,229,30,242,71,130,4,137,222,4,35,55,113,110,16,22,
10106 78,81,239,36,120,32,72,157,224,64,147,138,25,237,0,52,72,242,2,126,82,3,74,
10107 129,148,227,234,66,12,112,28,140,155,104,203,169,158,9,133,158,4,25,36,1,
10108 61,96,47,181,80,46,132,128,255,223,255,255,255,255,255,254,39,172,67,118,
10109 170,5,208,144,0,0,0,0,0,0,0,0,115,16,31,254,0,0,0,0,0,0,8,245,238,146,38,
10110 138,147,105,13,42,26,137,226,3,255,128,0,0,0,0,0,1,30,180,134,4,209,82,109,
10111 33,165,67,81,60,64,255,240,0,0,0,0,0,0,28,144,155,104,0,0,0,0,0,0,0,0,16,
10112 117,59,130,48,155,98,48,187,144,3,205,220,42,46,65,237,72,27,55,112,151,
10113 123,154,70,205,0,94,208,129,115,119,31,18,9,18,67,155,183,34,12,176,96,175,
10114 4,100,74,228,3,237,38,43,31,192,109,117,171,0,228,164,219,72,127,248,0,0,0,
10115 0,0,0,196,234,111,0,50,110,224,193,50,114,83,138,26,107,192,131,38,238,77,
10116 12,39,37,56,161,166,188,11,132,188,12,74,110,226,220,32,44,156,24,38,78,74,
10117 113,67,77,120,28,148,221,197,184,64,89,57,52,48,156,148,226,134,154,240,64,
10118 195,94,8,56,123,193,11,85,116,140,45,240,3,152,147,228,208,194,95,0,89,137,
10119 62,22,139,95,48,64,70,200,67,28,98,79,180,152,139,218,45,124,193,1,27,33,
10120 16,65,137,62,49,205,153,236,132,81,102,36,251,73,137,157,115,102,123,33,24,
10121 57,137,62,12,19,37,144,142,40,196,159,105,49,15,160,153,44,132,128,198,36,
10122 248,48,98,200,73,18,98,79,180,152,135,208,98,200,74,16,98,79,135,117,35,43,
10123 33,44,89,137,62,210,98,63,93,72,202,200,76,20,98,79,140,67,105,50,74,200,
10124 77,26,98,79,180,152,153,212,54,147,36,172,132,225,70,36,249,34,9,205,28,
10125 172,132,241,166,36,251,73,138,93,32,156,209,202,200,80,30,98,79,140,66,214,
10126 137,16,78,104,229,100,40,146,49,39,218,76,76,234,22,180,72,130,115,71,43,
10127 33,72,137,137,62,77,12,38,92,210,113,197,44,137,59,64,7,145,39,201,161,132,
10128 184,64,249,18,124,98,22,180,72,130,115,71,43,101,76,148,137,62,210,98,103,
10129 80,181,162,68,19,154,57,91,42,130,164,73,242,68,19,154,57,91,95,84,108,137,
10130 62,210,98,151,72,39,52,114,182,190,176,169,18,124,98,27,73,146,86,223,215,
10131 27,34,79,180,152,153,212,54,147,36,173,191,176,34,68,159,14,234,70,86,231,
10132 217,23,34,79,180,152,143,215,82,50,183,62,208,121,18,124,24,38,75,101,108,
10133 84,137,62,210,98,31,65,50,91,43,130,36,73,241,142,108,207,109,125,209,114,
10134 36,251,73,137,157,115,102,123,107,239,11,145,39,194,209,107,230,8,8,219,
10135 127,124,116,137,62,210,98,47,104,181,243,4,4,109,191,192,135,49,39,204,16,
10136 17,178,24,32,242,36,249,130,2,54,203,7,6,104,14,76,131,140,144,0,0,0,0,0,0,
10137 0,1,141,207,215,12,78,126,193,46,190,126,192,98,179,246,4,197,231,236,10,
10138 193,9,114,11,172,64,73,146,83,236,145,169,237,1,6,120,14,78,129,179,40,249,
10139 18,149,175,207,141,199,27,76,248,156,81,177,207,139,198,9,169,199,129,58,
10140 136,19,202,11,179,20,240,149,2,248,72,197,209,200,148,162,117,48,39,148,
10141 151,102,42,228,64,211,19,132,140,93,28,137,74,39,85,2,121,81,118,98,238,68,
10142 133,36,72,209,19,132,140,93,28,137,74,39,87,2,121,89,118,98,190,75,13,152,
10143 47,194,70,46,142,68,165,19,172,129,60,176,187,49,79,39,135,147,132,140,93,
10144 28,137,74,39,91,2,121,105,118,98,142,210,40,39,99,23,71,34,82,135,8,128,
10145 120,72,8,0,183,225,81,98,138,237,33,58,182,232,232,64,64,2,107,177,187,181,
10146 85,22,7,213,183,74,1,255,49,114,23,247,209,207,120,94,173,198,210,36,3,255,
10147 113,84,118,82,184,47,224,221,91,141,163,160,72,7,251,121,111,98,164,220,
10148 161,192,186,244,64,64,9,33,251,84,68,45,24,15,217,66,51,209,218,210,128,
10149 127,205,65,60,204,254,119,154,23,178,132,103,165,0,255,218,130,121,153,252,
10150 239,52,167,224,121,44,48,46,95,203,166,238,74,113,67,77,201,128,219,152,
10151 164,82,6,0,203,76,64,64,9,210,211,18,4,4,144,221,49,40,64,76,13,211,19,5,4,
10152 192,221,45,66,1,4,24,207,76,82,2,8,136,94,152,156,24,157,45,49,64,6,75,191,
10153 76,80,66,149,110,116,116,197,8,41,240,247,79,70,188,6,183,27,76,80,194,45,
10154 198,210,211,20,144,171,113,180,116,52,197,40,27,1,125,34,240,27,16,221,42,
10155 240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,33,
10156 186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,183,
10157 1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,140,
10158 144,230,192,64,211,136,0,0,0,0,0,182,120,43,135,126,16,68,52,174,195,144,
10159 12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,32,
10160 176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,35,
10161 18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,236,
10162 224,175,131,117,2,178,112,145,139,163,145,131,114,70,46,142,218,27,182,72,
10163 197,209,219,56,26,53,161,166,32,128,56,18,2,129,239,94,50,76,130,68,230,
10164 202,113,160,167,146,94,163,134,66,161,164,227,226,231,146,51,198,249,147,
10165 71,209,67,73,210,94,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,
10166 155,163,191,68,28,98,79,143,139,166,233,225,228,227,139,198,37,210,244,208,
10167 24,137,112,151,153,27,36,5,100,224,146,105,184,100,196,95,18,84,141,159,9,
10168 121,145,178,67,155,46,33,38,187,168,252,211,243,81,92,2,14,40,16,50,37,202,
10169 160,150,154,67,152,148,20,28,76,156,89,26,105,158,63,232,16,44,150,129,18,
10170 146,44,28,96,14,98,216,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
10171 113,75,34,78,63,236,3,6,133,41,35,31,242,18,195,152,147,226,27,61,138,41,
10172 140,16,98,79,148,67,103,177,69,45,136,49,39,196,54,122,58,212,83,26,36,196,
10173 159,40,134,207,71,90,138,92,16,98,79,136,108,244,244,168,166,56,73,137,62,
10174 81,13,158,158,149,20,186,40,196,159,10,183,2,122,122,84,82,240,163,18,124,
10175 42,220,9,235,106,81,75,225,228,73,241,13,158,197,54,198,8,145,39,202,33,
10176 179,216,166,214,196,72,147,226,27,61,29,106,109,141,19,34,79,148,67,103,
10177 163,173,77,174,8,145,39,196,54,122,122,84,219,28,38,68,159,40,134,207,79,
10178 74,155,93,21,34,79,133,91,129,61,61,42,109,120,84,137,62,21,110,4,245,181,
10179 41,181,248,56,224,28,24,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
10180 113,75,34,78,63,236,3,6,133,41,35,31,242,11,174,254,160,34,84,8,35,16,98,
10181 146,38,55,32,33,30,135,19,36,182,158,72,237,17,100,97,27,56,7,254,0,0,0,0,
10182 0,0,6,56,199,161,30,135,19,36,182,158,72,237,17,100,97,27,56,7,254,0,0,0,0,
10183 0,0,6,55,36,33,30,135,19,36,182,158,72,237,17,100,97,27,56,7,254,0,0,0,0,0,
10184 0,10,40,11,91,133,199,172,8,111,248,128,239,88,16,222,56,191,242,49,198,69,
10185 8,244,56,153,37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,49,185,
10186 65,8,244,56,153,37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,49,
10187 198,77,8,244,56,153,37,180,242,71,104,139,35,8,217,192,63,240,0,0,0,0,0,0,
10188 49,185,97,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,
10189 49,198,85,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,
10190 49,185,129,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,
10191 0,49,198,93,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,0,0,0,0,0,0,
10192 0,49,185,161,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,
10193 0,0,49,198,101,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,0,
10194 0,0,0,49,185,193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,0,
10195 0,0,0,0,49,198,109,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,0,
10196 0,0,0,0,0,49,185,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,16,
10197 0,0,0,0,0,0,49,198,117,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,
10198 16,0,0,0,0,0,0,49,186,1,8,244,56,153,37,180,242,71,104,139,35,8,217,192,64,
10199 32,0,0,0,0,0,0,49,198,125,8,244,56,153,37,180,242,71,104,139,35,8,217,192,
10200 64,32,0,0,0,0,0,0,32,232,130,0,97,57,162,4,245,72,10,68,184,70,137,195,67,
10201 77,175,32,66,37,192,208,165,36,117,196,10,14,38,78,44,141,52,207,169,64,56,
10202 156,199,130,36,160,141,146,52,38,32,76,72,1,246,136,235,103,177,69,1,17,32,
10203 7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,171,37,20,65,145,32,7,
10204 218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,158,142,183,86,74,41,48,
10205 92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,246,136,235,103,167,165,
10206 213,146,138,40,200,144,3,237,17,214,207,79,75,161,37,20,138,46,36,0,248,
10207 134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,75,161,37,20,170,46,36,
10208 0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,39,208,146,138,70,25,18,
10209 0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,129,89,58,18,81,72,226,
10210 162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,17,214,207,161,37,22,144,
10211 38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,207,161,37,22,176,42,209,
10212 68,201,218,35,173,158,197,54,4,218,40,153,56,134,207,98,155,75,27,104,162,
10213 100,237,17,214,207,71,91,171,37,54,65,182,138,38,78,209,29,108,244,117,186,
10214 18,83,104,131,45,20,76,156,67,103,163,173,213,146,155,76,25,104,162,100,
10215 226,27,61,29,110,132,148,218,160,219,69,19,39,104,142,182,122,122,93,89,41,
10216 178,141,180,81,50,118,136,235,103,167,165,208,146,155,69,25,104,162,100,
10217 226,27,61,61,46,172,148,218,104,203,69,19,39,16,217,233,233,116,36,166,213,
10218 70,90,40,153,56,85,184,19,234,201,77,152,101,162,137,147,133,91,129,62,132,
10219 148,218,48,219,69,19,39,6,234,5,100,234,201,77,156,109,162,137,147,131,117,
10220 2,178,116,36,166,209,197,218,40,153,59,68,117,179,234,201,78,32,11,180,81,
10221 50,118,136,235,103,208,146,156,72,21,104,162,100,226,27,62,172,148,226,128,
10222 171,69,19,39,16,217,244,36,167,22,53,59,22,53,91,0,2,21,11,94,181,128,196,
10223 133,0,185,80,32,56,156,199,130,36,160,72,16,78,126,53,144,5,146,208,34,82,
10224 72,1,109,20,76,155,40,32,233,0,115,70,130,8,209,56,104,105,187,252,193,3,
10225 17,162,112,201,242,18,65,211,0,230,149,132,17,162,112,208,211,119,248,0,82,
10226 130,96,95,127,128,130,80,102,186,36,232,92,206,255,1,80,48,200,39,12,158,
10227 241,64,
10228 };
10229 #elif defined(DUK_USE_DOUBLE_ME)
10230 DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
10231 144,148,105,221,32,68,52,228,62,12,104,200,165,134,148,248,81,77,61,191,
10232 135,35,154,103,34,72,6,157,159,197,145,77,245,126,52,130,106,234,163,196,
10233 52,226,18,51,161,26,113,1,60,37,64,190,18,49,116,116,33,26,113,1,92,136,26,
10234 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
10235 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
10236 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
10237 147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
10238 116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
10239 15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
10240 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
10241 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
10242 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
10243 128,0,1,240,254,0,0,0,1,153,128,0,1,224,254,0,0,0,1,151,137,0,214,9,188,35,
10244 131,12,225,196,56,177,78,60,99,147,28,229,200,57,162,120,74,129,124,36,98,
10245 232,156,241,92,136,26,98,112,145,139,162,116,71,114,36,41,34,70,136,156,36,
10246 98,232,157,49,124,150,27,48,95,132,140,93,19,170,39,147,195,201,194,70,46,
10247 137,215,17,218,69,4,236,98,232,157,153,39,110,81,220,15,193,209,83,3,200,
10248 119,130,241,241,117,240,120,80,252,137,10,178,10,103,134,180,122,9,135,136,
10249 154,120,169,199,142,158,121,10,7,146,162,121,74,71,150,166,121,138,135,154,
10250 170,121,202,199,158,23,201,146,243,225,26,39,12,145,61,16,190,76,151,159,6,
10251 65,56,100,137,233,35,93,205,144,33,224,140,137,196,54,121,244,5,60,17,145,
10252 56,85,184,19,207,16,21,18,227,65,198,231,72,16,137,112,168,106,38,76,225,2,
10253 70,65,56,100,237,34,140,177,4,134,65,56,100,237,34,129,117,204,123,154,70,
10254 207,46,64,146,52,78,25,59,72,163,48,65,34,52,78,25,59,72,160,93,115,30,230,
10255 145,179,204,144,24,146,16,30,76,209,2,40,210,72,64,121,52,4,0,156,88,97,5,
10256 194,96,227,18,124,124,93,55,79,15,39,28,94,49,38,159,154,136,96,196,159,29,
10257 102,241,241,115,201,25,227,131,36,133,20,62,110,142,253,2,102,36,248,235,
10258 55,143,139,158,72,207,28,104,24,73,112,201,3,2,82,65,155,187,94,6,20,72,9,
10259 147,120,128,225,144,168,105,56,248,185,228,140,241,190,96,128,200,84,52,
10260 156,124,92,242,70,104,36,183,168,4,145,0,190,41,1,139,18,19,36,226,146,17,
10261 124,73,82,54,124,37,230,70,201,14,108,184,132,8,68,185,34,1,100,31,8,129,8,
10262 151,11,23,100,141,225,18,12,68,184,75,204,141,146,2,178,112,72,8,162,98,92,
10263 50,10,152,147,227,172,222,62,46,121,35,60,114,88,96,92,185,112,201,65,34,
10264 92,4,1,147,81,159,141,205,32,234,121,96,97,57,64,97,121,128,14,56,37,199,
10265 89,188,124,92,242,70,120,227,144,53,18,227,226,233,186,120,121,56,226,242,
10266 8,40,248,185,228,140,241,196,75,132,109,24,72,128,43,39,36,136,48,64,114,0,
10267 250,156,168,1,64,247,175,25,36,2,8,11,94,80,248,16,40,104,242,103,200,48,
10268 193,3,162,92,4,98,12,41,14,66,40,106,101,1,132,130,8,24,78,104,129,54,62,
10269 96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,178,
10270 58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,129,
10271 232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,201,
10272 126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,132,
10273 0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,46,
10274 36,29,4,78,69,6,60,226,31,192,7,255,252,24,160,163,11,23,51,130,56,35,193,
10275 56,100,238,31,6,150,46,103,4,225,147,143,114,27,62,233,241,200,137,182,133,
10276 42,142,167,216,6,23,216,0,97,28,17,224,39,223,32,80,142,8,240,78,25,56,9,
10277 248,8,22,39,12,156,123,144,217,240,19,240,18,6,19,154,32,79,194,124,14,134,
10278 140,151,227,139,226,52,11,88,37,62,33,163,37,248,226,248,141,32,213,184,64,
10279 89,56,39,49,224,137,60,100,5,96,38,35,249,8,15,18,61,96,17,60,200,6,145,1,
10280 17,31,206,64,89,45,2,39,161,0,178,122,209,63,74,2,101,64,202,113,67,77,235,
10281 64,92,221,197,186,196,143,4,9,19,188,1,25,187,139,112,128,178,113,110,177,
10282 35,193,2,68,239,0,46,110,229,30,242,71,130,4,137,222,4,35,55,113,110,16,22,
10283 78,81,239,36,120,32,72,157,224,64,147,138,25,237,0,52,72,242,2,126,82,3,74,
10284 129,148,227,234,66,12,112,28,140,155,104,203,169,158,9,133,158,4,25,36,1,
10285 61,96,47,181,80,46,132,129,255,255,222,255,255,255,255,254,39,172,67,118,
10286 170,5,208,144,0,0,0,0,0,64,0,0,51,16,0,0,62,31,192,0,0,0,8,245,238,146,38,
10287 138,147,105,13,42,26,137,226,0,0,7,131,248,0,0,0,1,30,180,134,4,209,82,109,
10288 33,165,67,81,60,64,0,0,240,255,0,0,0,0,28,144,155,104,0,0,0,0,0,0,0,0,16,
10289 117,59,130,48,155,98,48,187,144,3,205,220,42,46,65,237,72,27,55,112,151,
10290 123,154,70,205,0,94,208,129,115,119,31,18,9,18,67,155,183,34,12,176,96,175,
10291 4,100,74,228,3,237,38,43,31,192,109,117,171,0,228,164,219,72,0,0,248,127,0,
10292 0,0,0,196,234,111,0,50,110,224,193,50,114,83,138,26,107,192,131,38,238,77,
10293 12,39,37,56,161,166,188,11,132,188,12,74,110,226,220,32,44,156,24,38,78,74,
10294 113,67,77,120,28,148,221,197,184,64,89,57,52,48,156,148,226,134,154,240,64,
10295 195,94,8,56,123,193,11,85,116,140,45,240,3,152,147,228,208,194,95,0,89,137,
10296 62,22,139,95,48,64,70,200,67,28,98,79,180,152,139,218,45,124,193,1,27,33,
10297 16,65,137,62,49,205,153,236,132,81,102,36,251,73,137,157,115,102,123,33,24,
10298 57,137,62,12,19,37,144,142,40,196,159,105,49,15,160,153,44,132,128,198,36,
10299 248,48,98,200,73,18,98,79,180,152,135,208,98,200,74,16,98,79,135,117,35,43,
10300 33,44,89,137,62,210,98,63,93,72,202,200,76,20,98,79,140,67,105,50,74,200,
10301 77,26,98,79,180,152,153,212,54,147,36,172,132,225,70,36,249,34,9,205,28,
10302 172,132,241,166,36,251,73,138,93,32,156,209,202,200,80,30,98,79,140,66,214,
10303 137,16,78,104,229,100,40,146,49,39,218,76,76,234,22,180,72,130,115,71,43,
10304 33,72,137,137,62,77,12,38,92,210,113,197,44,137,59,64,7,145,39,201,161,132,
10305 184,64,249,18,124,98,22,180,72,130,115,71,43,101,76,148,137,62,210,98,103,
10306 80,181,162,68,19,154,57,91,42,130,164,73,242,68,19,154,57,91,95,84,108,137,
10307 62,210,98,151,72,39,52,114,182,190,176,169,18,124,98,27,73,146,86,223,215,
10308 27,34,79,180,152,153,212,54,147,36,173,191,176,34,68,159,14,234,70,86,231,
10309 217,23,34,79,180,152,143,215,82,50,183,62,208,121,18,124,24,38,75,101,108,
10310 84,137,62,210,98,31,65,50,91,43,130,36,73,241,142,108,207,109,125,209,114,
10311 36,251,73,137,157,115,102,123,107,239,11,145,39,194,209,107,230,8,8,219,
10312 127,124,116,137,62,210,98,47,104,181,243,4,4,109,191,192,135,49,39,204,16,
10313 17,178,24,32,242,36,249,130,2,54,203,7,6,104,14,76,131,140,144,0,0,0,0,0,0,
10314 0,1,141,207,215,12,78,126,193,46,190,126,192,98,179,246,4,197,231,236,10,
10315 193,9,114,11,172,64,73,146,83,236,145,169,237,1,6,120,14,78,129,179,40,249,
10316 18,149,175,207,141,199,27,76,248,156,81,177,207,139,198,9,169,199,129,58,
10317 136,19,202,11,179,20,240,149,2,248,72,197,209,200,148,162,117,48,39,148,
10318 151,102,42,228,64,211,19,132,140,93,28,137,74,39,85,2,121,81,118,98,238,68,
10319 133,36,72,209,19,132,140,93,28,137,74,39,87,2,121,89,118,98,190,75,13,152,
10320 47,194,70,46,142,68,165,19,172,129,60,176,187,49,79,39,135,147,132,140,93,
10321 28,137,74,39,91,2,121,105,118,98,142,210,40,39,99,23,71,34,82,135,8,128,
10322 120,72,1,87,224,168,13,42,226,145,97,58,182,232,232,64,177,107,2,64,22,85,
10323 181,187,7,213,183,74,2,17,119,49,255,121,207,215,240,94,173,198,210,36,4,
10324 113,95,115,255,232,34,182,80,221,91,141,163,160,72,15,121,123,103,225,220,
10325 164,194,160,186,244,64,251,33,9,64,24,45,68,84,15,217,66,51,209,218,210,
10326 129,61,65,204,127,154,118,254,204,23,178,132,103,165,2,122,131,216,255,52,
10327 237,253,152,167,224,121,44,48,46,95,203,166,238,74,113,67,77,201,128,219,
10328 152,164,82,6,0,203,76,64,64,9,210,211,18,4,4,144,221,49,40,64,76,13,211,19,
10329 5,4,192,221,45,66,1,4,24,207,76,82,2,8,136,94,152,156,24,157,45,49,64,6,75,
10330 191,76,80,66,149,110,116,116,197,8,41,240,247,79,70,188,6,183,27,76,80,194,
10331 45,198,210,211,20,144,171,113,180,116,52,197,40,27,1,125,34,240,27,16,221,
10332 42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
10333 33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
10334 183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
10335 140,144,230,192,0,136,211,64,0,0,0,0,182,120,43,135,126,16,68,52,174,195,
10336 144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
10337 32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
10338 35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
10339 236,224,175,131,117,2,178,112,145,139,163,145,131,114,70,46,142,218,27,182,
10340 72,197,209,219,56,26,53,161,166,32,128,56,18,2,129,239,94,50,76,130,68,230,
10341 202,113,160,167,146,94,163,134,66,161,164,227,226,231,146,51,198,249,147,
10342 71,209,67,73,210,94,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,
10343 155,163,191,68,28,98,79,143,139,166,233,225,228,227,139,198,37,210,244,208,
10344 24,137,112,151,153,27,36,5,100,224,146,105,184,100,196,95,18,84,141,159,9,
10345 121,145,178,67,155,46,33,38,187,168,252,211,243,81,92,2,14,40,16,50,37,202,
10346 160,150,154,67,152,148,20,28,76,156,89,26,105,158,63,232,16,44,150,129,18,
10347 146,44,28,96,14,98,216,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
10348 113,75,34,78,63,236,3,6,133,41,35,31,242,18,195,152,147,226,27,61,138,41,
10349 140,16,98,79,148,67,103,177,69,45,136,49,39,196,54,122,58,212,83,26,36,196,
10350 159,40,134,207,71,90,138,92,16,98,79,136,108,244,244,168,166,56,73,137,62,
10351 81,13,158,158,149,20,186,40,196,159,10,183,2,122,122,84,82,240,163,18,124,
10352 42,220,9,235,106,81,75,225,228,73,241,13,158,197,54,198,8,145,39,202,33,
10353 179,216,166,214,196,72,147,226,27,61,29,106,109,141,19,34,79,148,67,103,
10354 163,173,77,174,8,145,39,196,54,122,122,84,219,28,38,68,159,40,134,207,79,
10355 74,155,93,21,34,79,133,91,129,61,61,42,109,120,84,137,62,21,110,4,245,181,
10356 41,181,248,56,224,28,24,80,113,50,113,100,105,166,120,255,160,20,28,76,156,
10357 113,75,34,78,63,236,3,6,133,41,35,31,242,11,174,254,160,34,84,8,35,16,98,
10358 146,38,55,32,33,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,30,7,224,0,
10359 0,0,6,56,199,161,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,30,7,224,
10360 0,0,0,6,55,36,33,30,135,19,36,182,158,72,237,17,100,97,27,56,0,0,30,7,224,
10361 0,0,0,10,40,11,91,133,199,172,8,111,248,128,239,88,16,222,56,191,242,49,
10362 198,69,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,
10363 49,185,65,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,
10364 0,49,198,77,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,
10365 0,0,49,185,97,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,
10366 0,0,49,198,85,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,
10367 0,0,49,185,129,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,
10368 0,0,0,49,198,93,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,
10369 0,0,0,49,185,161,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,
10370 0,0,0,0,49,198,101,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,
10371 64,0,0,0,0,49,185,193,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,
10372 16,64,0,0,0,0,49,198,109,8,244,56,153,37,180,242,71,104,139,35,8,217,192,0,
10373 0,16,64,0,0,0,0,49,185,225,8,244,56,153,37,180,242,71,104,139,35,8,217,192,
10374 0,0,16,64,0,0,0,0,49,198,117,8,244,56,153,37,180,242,71,104,139,35,8,217,
10375 192,0,0,16,64,0,0,0,0,49,186,1,8,244,56,153,37,180,242,71,104,139,35,8,217,
10376 192,0,0,32,64,0,0,0,0,49,198,125,8,244,56,153,37,180,242,71,104,139,35,8,
10377 217,192,0,0,32,64,0,0,0,0,32,232,130,0,97,57,162,4,245,72,10,68,184,70,137,
10378 195,67,77,175,32,66,37,192,208,165,36,117,196,10,14,38,78,44,141,52,207,
10379 169,64,56,156,199,130,36,160,141,146,52,38,32,76,72,1,246,136,235,103,177,
10380 69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,171,37,20,
10381 65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,158,142,183,
10382 86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,246,136,235,
10383 103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,37,20,138,46,
10384 36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,75,161,37,20,
10385 170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,39,208,146,138,
10386 70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,129,89,58,18,
10387 81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,17,214,207,161,
10388 37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,207,161,37,22,
10389 176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,207,98,155,75,
10390 27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,78,209,29,108,
10391 244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,146,155,76,25,
10392 104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,104,142,182,122,
10393 122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,146,155,69,25,
10394 104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,217,233,233,
10395 116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,162,137,147,
10396 133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,77,156,109,
10397 162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,117,179,234,
10398 201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,162,100,226,
10399 27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,59,22,53,91,0,2,
10400 21,11,94,181,128,196,133,0,185,80,32,56,156,199,130,36,160,72,16,78,126,53,
10401 144,5,146,208,34,82,72,1,109,20,76,155,40,32,233,0,115,70,130,8,209,56,104,
10402 105,187,252,193,3,17,162,112,201,242,18,65,211,0,230,149,132,17,162,112,
10403 208,211,119,248,0,82,130,96,95,127,128,130,80,102,186,36,232,92,206,255,1,
10404 80,48,200,39,12,158,241,64,
10405 };
10406 #else
10407 #error invalid endianness defines
10408 #endif
10409 #endif /* DUK_USE_ROM_OBJECTS */
10410 /*
10411  * Error and fatal handling.
10412  */
10413 
10414 /* #include duk_internal.h -> already included */
10415 
10416 #define DUK__ERRFMT_BUFSIZE 256 /* size for formatting buffers */
10417 
10418 #if defined(DUK_USE_VERBOSE_ERRORS)
10419 
10420 DUK_INTERNAL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {
10421  va_list ap;
10422  char msg[DUK__ERRFMT_BUFSIZE];
10423  va_start(ap, fmt);
10424  (void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
10425  msg[sizeof(msg) - 1] = (char) 0;
10426  duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
10427  va_end(ap); /* dead code, but ensures portability (see Linux man page notes) */
10428 }
10429 
10430 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
10431  duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
10432 }
10433 
10434 #else /* DUK_USE_VERBOSE_ERRORS */
10435 
10436 DUK_INTERNAL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
10437  duk_err_create_and_throw(thr, code);
10438 }
10439 
10440 #endif /* DUK_USE_VERBOSE_ERRORS */
10441 
10442 /*
10443  * Error throwing helpers
10444  */
10445 
10446 #if defined(DUK_USE_VERBOSE_ERRORS)
10447 #if defined(DUK_USE_PARANOID_ERRORS)
10448 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
10449  DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
10450  expect_name, duk_get_type_name((duk_context *) thr, idx), (long) idx);
10451 }
10452 #else
10453 DUK_INTERNAL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {
10454  DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
10455  expect_name, duk_push_string_readable((duk_context *) thr, idx), (long) idx);
10456 }
10457 #endif
10458 DUK_INTERNAL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10459  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
10460 }
10461 DUK_INTERNAL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10462  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
10463 }
10464 DUK_INTERNAL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
10465  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
10466 }
10467 DUK_INTERNAL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
10468  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
10469 }
10470 DUK_INTERNAL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
10471  DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
10472 }
10473 DUK_INTERNAL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10474  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
10475 }
10476 DUK_INTERNAL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10477  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
10478 }
10479 DUK_INTERNAL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10480  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
10481 }
10482 DUK_INTERNAL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
10483  DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
10484 }
10485 #else
10486 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
10487  * when non-verbose errors are used.
10488  */
10489 
10490 DUK_NORETURN(DUK_LOCAL_DECL void duk__err_shared(duk_hthread *thr, duk_uint_t code));
10491 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_uint_t code) {
10492  DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
10493 }
10494 DUK_INTERNAL void duk_err_error(duk_hthread *thr) {
10495  duk__err_shared(thr, DUK_ERR_ERROR);
10496 }
10497 DUK_INTERNAL void duk_err_range(duk_hthread *thr) {
10498  duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
10499 }
10500 DUK_INTERNAL void duk_err_eval(duk_hthread *thr) {
10501  duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
10502 }
10503 DUK_INTERNAL void duk_err_reference(duk_hthread *thr) {
10504  duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
10505 }
10506 DUK_INTERNAL void duk_err_syntax(duk_hthread *thr) {
10507  duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
10508 }
10509 DUK_INTERNAL void duk_err_type(duk_hthread *thr) {
10510  duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
10511 }
10512 DUK_INTERNAL void duk_err_uri(duk_hthread *thr) {
10513  duk__err_shared(thr, DUK_ERR_URI_ERROR);
10514 }
10515 #endif
10516 
10517 /*
10518  * Default fatal error handler
10519  */
10520 
10521 DUK_INTERNAL void duk_default_fatal_handler(void *udata, const char *msg) {
10522  DUK_UNREF(udata);
10523  DUK_UNREF(msg);
10524 
10525 #if defined(DUK_USE_FATAL_HANDLER)
10526  /* duk_config.h provided a custom default fatal handler. */
10527  DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg ? msg : "NULL"));
10528  DUK_USE_FATAL_HANDLER(udata, msg);
10529 #else
10530  /* Default behavior is to abort() on error. There's no printout
10531  * which makes this awkward, so it's always recommended to use an
10532  * explicit fatal error handler.
10533  */
10534  DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg ? msg : "NULL"));
10535  DUK_ABORT();
10536 #endif
10537 
10538  DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
10539  for (;;) {
10540  /* Loop forever to ensure we don't return. */
10541  }
10542 }
10543 
10544 /* automatic undefs */
10545 #undef DUK__ERRFMT_BUFSIZE
10546 /*
10547  * Various Unicode help functions for character classification predicates,
10548  * case conversion, decoding, etc.
10549  */
10550 
10551 /* #include duk_internal.h -> already included */
10552 
10553 /*
10554  * Fast path tables
10555  */
10556 
10557 #if defined(DUK_USE_IDCHAR_FASTPATH)
10558 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
10559  /* 0: not IdentifierStart or IdentifierPart
10560  * 1: IdentifierStart and IdentifierPart
10561  * -1: IdentifierPart only
10562  */
10563  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00...0x0f */
10564  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10...0x1f */
10565  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20...0x2f */
10566  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, /* 0x30...0x3f */
10567  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40...0x4f */
10568  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50...0x5f */
10569  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60...0x6f */
10570  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70...0x7f */
10571 };
10572 #endif
10573 
10574 /*
10575  * XUTF-8 and CESU-8 encoding/decoding
10576  */
10577 
10578 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
10579  duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
10580  if (x < 0x80UL) {
10581  /* 7 bits */
10582  return 1;
10583  } else if (x < 0x800UL) {
10584  /* 11 bits */
10585  return 2;
10586  } else if (x < 0x10000UL) {
10587  /* 16 bits */
10588  return 3;
10589  } else if (x < 0x200000UL) {
10590  /* 21 bits */
10591  return 4;
10592  } else if (x < 0x4000000UL) {
10593  /* 26 bits */
10594  return 5;
10595  } else if (x < (duk_ucodepoint_t) 0x80000000UL) {
10596  /* 31 bits */
10597  return 6;
10598  } else {
10599  /* 36 bits */
10600  return 7;
10601  }
10602 }
10603 
10604 #if defined(DUK_USE_ASSERTIONS)
10605 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
10606  duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
10607  if (x < 0x80UL) {
10608  /* 7 bits */
10609  return 1;
10610  } else if (x < 0x800UL) {
10611  /* 11 bits */
10612  return 2;
10613  } else if (x < 0x10000UL) {
10614  /* 16 bits */
10615  return 3;
10616  } else {
10617  /* Encoded as surrogate pair, each encoding to 3 bytes for
10618  * 6 bytes total. Codepoints above U+10FFFF encode as 6 bytes
10619  * too, see duk_unicode_encode_cesu8().
10620  */
10621  return 3 + 3;
10622  }
10623 }
10624 #endif /* DUK_USE_ASSERTIONS */
10625 
10626 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
10627  0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
10628 };
10629 
10630 /* Encode to extended UTF-8; 'out' must have space for at least
10631  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes. Allows encoding of any
10632  * 32-bit (unsigned) codepoint.
10633  */
10634 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
10635  duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
10636  duk_small_int_t len;
10637  duk_uint8_t marker;
10638  duk_small_int_t i;
10639 
10640  len = duk_unicode_get_xutf8_length(cp);
10641  DUK_ASSERT(len > 0);
10642 
10643  marker = duk_unicode_xutf8_markers[len - 1]; /* 64-bit OK because always >= 0 */
10644 
10645  i = len;
10646  DUK_ASSERT(i > 0);
10647  do {
10648  i--;
10649  if (i > 0) {
10650  out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
10651  x >>= 6;
10652  } else {
10653  /* Note: masking of 'x' is not necessary because of
10654  * range check and shifting -> no bits overlapping
10655  * the marker should be set.
10656  */
10657  out[0] = (duk_uint8_t) (marker + x);
10658  }
10659  } while (i > 0);
10660 
10661  return len;
10662 }
10663 
10664 /* Encode to CESU-8; 'out' must have space for at least
10665  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
10666  * will encode to garbage but won't overwrite the output buffer.
10667  */
10668 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
10669  duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
10670  duk_small_int_t len;
10671 
10672  if (x < 0x80UL) {
10673  out[0] = (duk_uint8_t) x;
10674  len = 1;
10675  } else if (x < 0x800UL) {
10676  out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
10677  out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
10678  len = 2;
10679  } else if (x < 0x10000UL) {
10680  /* surrogate pairs get encoded here */
10681  out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
10682  out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
10683  out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
10684  len = 3;
10685  } else {
10686  /*
10687  * Unicode codepoints above U+FFFF are encoded as surrogate
10688  * pairs here. This ensures that all CESU-8 codepoints are
10689  * 16-bit values as expected in Ecmascript. The surrogate
10690  * pairs always get a 3-byte encoding (each) in CESU-8.
10691  * See: http://en.wikipedia.org/wiki/Surrogate_pair
10692  *
10693  * 20-bit codepoint, 10 bits (A and B) per surrogate pair:
10694  *
10695  * x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
10696  * sp1 = 0b110110AA AAAAAAAA (0xd800 + ((x >> 10) & 0x3ff))
10697  * sp2 = 0b110111BB BBBBBBBB (0xdc00 + (x & 0x3ff))
10698  *
10699  * Encoded into CESU-8:
10700  *
10701  * sp1 -> 0b11101101 (0xe0 + ((sp1 >> 12) & 0x0f))
10702  * -> 0b1010AAAA (0x80 + ((sp1 >> 6) & 0x3f))
10703  * -> 0b10AAAAAA (0x80 + (sp1 & 0x3f))
10704  * sp2 -> 0b11101101 (0xe0 + ((sp2 >> 12) & 0x0f))
10705  * -> 0b1011BBBB (0x80 + ((sp2 >> 6) & 0x3f))
10706  * -> 0b10BBBBBB (0x80 + (sp2 & 0x3f))
10707  *
10708  * Note that 0x10000 must be subtracted first. The code below
10709  * avoids the sp1, sp2 temporaries which saves around 20 bytes
10710  * of code.
10711  */
10712 
10713  x -= 0x10000UL;
10714 
10715  out[0] = (duk_uint8_t) (0xed);
10716  out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
10717  out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
10718  out[3] = (duk_uint8_t) (0xed);
10719  out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
10720  out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
10721  len = 6;
10722  }
10723 
10724  return len;
10725 }
10726 
10727 /* Decode helper. Return zero on error. */
10728 DUK_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) {
10729  const duk_uint8_t *p;
10730  duk_uint32_t res;
10731  duk_uint_fast8_t ch;
10732  duk_small_int_t n;
10733 
10734  DUK_UNREF(thr);
10735 
10736  p = *ptr;
10737  if (p < ptr_start || p >= ptr_end) {
10738  goto fail;
10739  }
10740 
10741  /*
10742  * UTF-8 decoder which accepts longer than standard byte sequences.
10743  * This allows full 32-bit code points to be used.
10744  */
10745 
10746  ch = (duk_uint_fast8_t) (*p++);
10747  if (ch < 0x80) {
10748  /* 0xxx xxxx [7 bits] */
10749  res = (duk_uint32_t) (ch & 0x7f);
10750  n = 0;
10751  } else if (ch < 0xc0) {
10752  /* 10xx xxxx -> invalid */
10753  goto fail;
10754  } else if (ch < 0xe0) {
10755  /* 110x xxxx 10xx xxxx [11 bits] */
10756  res = (duk_uint32_t) (ch & 0x1f);
10757  n = 1;
10758  } else if (ch < 0xf0) {
10759  /* 1110 xxxx 10xx xxxx 10xx xxxx [16 bits] */
10760  res = (duk_uint32_t) (ch & 0x0f);
10761  n = 2;
10762  } else if (ch < 0xf8) {
10763  /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx [21 bits] */
10764  res = (duk_uint32_t) (ch & 0x07);
10765  n = 3;
10766  } else if (ch < 0xfc) {
10767  /* 1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [26 bits] */
10768  res = (duk_uint32_t) (ch & 0x03);
10769  n = 4;
10770  } else if (ch < 0xfe) {
10771  /* 1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [31 bits] */
10772  res = (duk_uint32_t) (ch & 0x01);
10773  n = 5;
10774  } else if (ch < 0xff) {
10775  /* 1111 1110 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [36 bits] */
10776  res = (duk_uint32_t) (0);
10777  n = 6;
10778  } else {
10779  /* 8-byte format could be:
10780  * 1111 1111 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx [41 bits]
10781  *
10782  * However, this format would not have a zero bit following the
10783  * leading one bits and would not allow 0xFF to be used as an
10784  * "invalid xutf-8" marker for internal keys. Further, 8-byte
10785  * encodings (up to 41 bit code points) are not currently needed.
10786  */
10787  goto fail;
10788  }
10789 
10790  DUK_ASSERT(p >= ptr_start); /* verified at beginning */
10791  if (p + n > ptr_end) {
10792  /* check pointer at end */
10793  goto fail;
10794  }
10795 
10796  while (n > 0) {
10797  DUK_ASSERT(p >= ptr_start && p < ptr_end);
10798  ch = (duk_uint_fast8_t) (*p++);
10799 #if 0
10800  if (ch & 0xc0 != 0x80) {
10801  /* not a continuation byte */
10802  p--;
10803  *ptr = p;
10804  *out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
10805  return 1;
10806  }
10807 #endif
10808  res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
10809  n--;
10810  }
10811 
10812  *ptr = p;
10813  *out_cp = res;
10814  return 1;
10815 
10816  fail:
10817  return 0;
10818 }
10819 
10820 /* used by e.g. duk_regexp_executor.c, string built-ins */
10821 DUK_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) {
10822  duk_ucodepoint_t cp;
10823 
10824  if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
10825  return cp;
10826  }
10827  DUK_ERROR_INTERNAL(thr);
10828  DUK_UNREACHABLE();
10829  return 0;
10830 }
10831 
10832 /* Compute (extended) utf-8 length without codepoint encoding validation,
10833  * used for string interning.
10834  *
10835  * NOTE: This algorithm is performance critical, more so than string hashing
10836  * in some cases. It is needed when interning a string and needs to scan
10837  * every byte of the string with no skipping. Having an ASCII fast path
10838  * is useful if possible in the algorithm. The current algorithms were
10839  * chosen from several variants, based on x64 gcc -O2 testing. See:
10840  * https://github.com/svaarala/duktape/pull/422
10841  *
10842  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
10843  */
10844 
10845 #if defined(DUK_USE_PREFER_SIZE)
10846 /* Small variant; roughly 150 bytes smaller than the fast variant. */
10847 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
10848  const duk_uint8_t *p;
10849  const duk_uint8_t *p_end;
10850  duk_size_t ncont;
10851  duk_size_t clen;
10852 
10853  p = data;
10854  p_end = data + blen;
10855  ncont = 0;
10856  while (p != p_end) {
10857  duk_uint8_t x;
10858  x = *p++;
10859  if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10860  ncont++;
10861  }
10862  }
10863 
10864  DUK_ASSERT(ncont <= blen);
10865  clen = blen - ncont;
10866  DUK_ASSERT(clen <= blen);
10867  return clen;
10868 }
10869 #else /* DUK_USE_PREFER_SIZE */
10870 /* This seems like a good overall approach. Fast path for ASCII in 4 byte
10871  * blocks.
10872  */
10873 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
10874  const duk_uint8_t *p;
10875  const duk_uint8_t *p_end;
10876  const duk_uint32_t *p32_end;
10877  const duk_uint32_t *p32;
10878  duk_size_t ncont;
10879  duk_size_t clen;
10880 
10881  ncont = 0; /* number of continuation (non-initial) bytes in [0x80,0xbf] */
10882  p = data;
10883  p_end = data + blen;
10884  if (blen < 16) {
10885  goto skip_fastpath;
10886  }
10887 
10888  /* Align 'p' to 4; the input data may have arbitrary alignment.
10889  * End of string check not needed because blen >= 16.
10890  */
10891  while (((duk_size_t) (const void *) p) & 0x03U) {
10892  duk_uint8_t x;
10893  x = *p++;
10894  if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10895  ncont++;
10896  }
10897  }
10898 
10899  /* Full, aligned 4-byte reads. */
10900  p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
10901  p32 = (const duk_uint32_t *) (const void *) p;
10902  while (p32 != (const duk_uint32_t *) p32_end) {
10903  duk_uint32_t x;
10904  x = *p32++;
10905  if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
10906  ; /* ASCII fast path */
10907  } else {
10908  /* Flip highest bit of each byte which changes
10909  * the bit pattern 10xxxxxx into 00xxxxxx which
10910  * allows an easy bit mask test.
10911  */
10912  x ^= 0x80808080UL;
10913  if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
10914  ncont++;
10915  }
10916  if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
10917  ncont++;
10918  }
10919  if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
10920  ncont++;
10921  }
10922  if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
10923  ncont++;
10924  }
10925  }
10926  }
10927  p = (const duk_uint8_t *) p32;
10928  /* Fall through to handle the rest. */
10929 
10930  skip_fastpath:
10931  while (p != p_end) {
10932  duk_uint8_t x;
10933  x = *p++;
10934  if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
10935  ncont++;
10936  }
10937  }
10938 
10939  DUK_ASSERT(ncont <= blen);
10940  clen = blen - ncont;
10941  DUK_ASSERT(clen <= blen);
10942  return clen;
10943 }
10944 #endif /* DUK_USE_PREFER_SIZE */
10945 
10946 /*
10947  * Unicode range matcher
10948  *
10949  * Matches a codepoint against a packed bitstream of character ranges.
10950  * Used for slow path Unicode matching.
10951  */
10952 
10953 /* Must match tools/extract_chars.py, generate_match_table3(). */
10954 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
10955  duk_uint32_t t;
10956 
10957  t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
10958  if (t <= 0x0eU) {
10959  return t;
10960  }
10961  t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
10962  if (t <= 0xfdU) {
10963  return t + 0x0f;
10964  }
10965  if (t == 0xfeU) {
10966  t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
10967  return t + 0x0fU + 0xfeU;
10968  } else {
10969  t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
10970  return t + 0x0fU + 0xfeU + 0x1000UL;
10971  }
10972 }
10973 
10974 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
10975  duk_bitdecoder_ctx bd_ctx;
10976  duk_codepoint_t prev_re;
10977 
10978  DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
10979  bd_ctx.data = (const duk_uint8_t *) unitab;
10980  bd_ctx.length = (duk_size_t) unilen;
10981 
10982  prev_re = 0;
10983  for (;;) {
10984  duk_codepoint_t r1, r2;
10985  r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10986  if (r1 == 0) {
10987  break;
10988  }
10989  r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
10990 
10991  r1 = prev_re + r1;
10992  r2 = r1 + r2;
10993  prev_re = r2;
10994 
10995  /* [r1,r2] is the range */
10996 
10997  DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
10998  (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
10999  if (cp >= r1 && cp <= r2) {
11000  return 1;
11001  }
11002  }
11003 
11004  return 0;
11005 }
11006 
11007 /*
11008  * "WhiteSpace" production check.
11009  */
11010 
11011 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
11012  /*
11013  * E5 Section 7.2 specifies six characters specifically as
11014  * white space:
11015  *
11016  * 0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
11017  * 000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
11018  * 000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
11019  * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
11020  * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
11021  * FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
11022  *
11023  * It also specifies any Unicode category 'Zs' characters as white
11024  * space. These can be extracted with the "tools/extract_chars.py" script.
11025  * Current result:
11026  *
11027  * RAW OUTPUT:
11028  * ===========
11029  * 0020;SPACE;Zs;0;WS;;;;;N;;;;;
11030  * 00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
11031  * 1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
11032  * 180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
11033  * 2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
11034  * 2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
11035  * 2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11036  * 2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11037  * 2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11038  * 2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11039  * 2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11040  * 2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
11041  * 2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11042  * 2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11043  * 200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11044  * 202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
11045  * 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
11046  * 3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
11047  *
11048  * RANGES:
11049  * =======
11050  * 0x0020
11051  * 0x00a0
11052  * 0x1680
11053  * 0x180e
11054  * 0x2000 ... 0x200a
11055  * 0x202f
11056  * 0x205f
11057  * 0x3000
11058  *
11059  * A manual decoder (below) is probably most compact for this.
11060  */
11061 
11062  duk_uint_fast8_t lo;
11063  duk_uint_fast32_t hi;
11064 
11065  /* cp == -1 (EOF) never matches and causes return value 0 */
11066 
11067  lo = (duk_uint_fast8_t) (cp & 0xff);
11068  hi = (duk_uint_fast32_t) (cp >> 8); /* does not fit into an uchar */
11069 
11070  if (hi == 0x0000UL) {
11071  if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
11072  lo == 0x20U || lo == 0xa0U) {
11073  return 1;
11074  }
11075  } else if (hi == 0x0020UL) {
11076  if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
11077  return 1;
11078  }
11079  } else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
11080  cp == 0xfeffL) {
11081  return 1;
11082  }
11083 
11084  return 0;
11085 }
11086 
11087 /*
11088  * "LineTerminator" production check.
11089  */
11090 
11091 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
11092  /*
11093  * E5 Section 7.3
11094  *
11095  * A LineTerminatorSequence essentially merges <CR> <LF> sequences
11096  * into a single line terminator. This must be handled by the caller.
11097  */
11098 
11099  if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
11100  cp == 0x2029L) {
11101  return 1;
11102  }
11103 
11104  return 0;
11105 }
11106 
11107 /*
11108  * "IdentifierStart" production check.
11109  */
11110 
11111 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
11112  /*
11113  * E5 Section 7.6:
11114  *
11115  * IdentifierStart:
11116  * UnicodeLetter
11117  * $
11118  * _
11119  * \ UnicodeEscapeSequence
11120  *
11121  * IdentifierStart production has one multi-character production:
11122  *
11123  * \ UnicodeEscapeSequence
11124  *
11125  * The '\' character is -not- matched by this function. Rather, the caller
11126  * should decode the escape and then call this function to check whether the
11127  * decoded character is acceptable (see discussion in E5 Section 7.6).
11128  *
11129  * The "UnicodeLetter" alternative of the production allows letters
11130  * from various Unicode categories. These can be extracted with the
11131  * "tools/extract_chars.py" script.
11132  *
11133  * Because the result has hundreds of Unicode codepoint ranges, matching
11134  * for any values >= 0x80 are done using a very slow range-by-range scan
11135  * and a packed range format.
11136  *
11137  * The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
11138  * it matters the most. The ASCII related ranges of IdentifierStart are:
11139  *
11140  * 0x0041 ... 0x005a ['A' ... 'Z']
11141  * 0x0061 ... 0x007a ['a' ... 'z']
11142  * 0x0024 ['$']
11143  * 0x005f ['_']
11144  */
11145 
11146  /* ASCII (and EOF) fast path -- quick accept and reject */
11147  if (cp <= 0x7fL) {
11148 #if defined(DUK_USE_IDCHAR_FASTPATH)
11149  return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
11150 #else
11151  if ((cp >= 'a' && cp <= 'z') ||
11152  (cp >= 'A' && cp <= 'Z') ||
11153  cp == '_' || cp == '$') {
11154  return 1;
11155  }
11156  return 0;
11157 #endif
11158  }
11159 
11160  /* Non-ASCII slow path (range-by-range linear comparison), very slow */
11161 
11162 #if defined(DUK_USE_SOURCE_NONBMP)
11163  if (duk__uni_range_match(duk_unicode_ids_noa,
11164  (duk_size_t) sizeof(duk_unicode_ids_noa),
11165  (duk_codepoint_t) cp)) {
11166  return 1;
11167  }
11168  return 0;
11169 #else
11170  if (cp < 0x10000L) {
11171  if (duk__uni_range_match(duk_unicode_ids_noabmp,
11172  sizeof(duk_unicode_ids_noabmp),
11173  (duk_codepoint_t) cp)) {
11174  return 1;
11175  }
11176  return 0;
11177  } else {
11178  /* without explicit non-BMP support, assume non-BMP characters
11179  * are always accepted as identifier characters.
11180  */
11181  return 1;
11182  }
11183 #endif
11184 }
11185 
11186 /*
11187  * "IdentifierPart" production check.
11188  */
11189 
11190 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
11191  /*
11192  * E5 Section 7.6:
11193  *
11194  * IdentifierPart:
11195  * IdentifierStart
11196  * UnicodeCombiningMark
11197  * UnicodeDigit
11198  * UnicodeConnectorPunctuation
11199  * <ZWNJ> [U+200C]
11200  * <ZWJ> [U+200D]
11201  *
11202  * IdentifierPart production has one multi-character production
11203  * as part of its IdentifierStart alternative. The '\' character
11204  * of an escape sequence is not matched here, see discussion in
11205  * duk_unicode_is_identifier_start().
11206  *
11207  * To match non-ASCII characters (codepoints >= 0x80), a very slow
11208  * linear range-by-range scan is used. The codepoint is first compared
11209  * to the IdentifierStart ranges, and if it doesn't match, then to a
11210  * set consisting of code points in IdentifierPart but not in
11211  * IdentifierStart. This is done to keep the unicode range data small,
11212  * at the expense of speed.
11213  *
11214  * The ASCII fast path consists of:
11215  *
11216  * 0x0030 ... 0x0039 ['0' ... '9', UnicodeDigit]
11217  * 0x0041 ... 0x005a ['A' ... 'Z', IdentifierStart]
11218  * 0x0061 ... 0x007a ['a' ... 'z', IdentifierStart]
11219  * 0x0024 ['$', IdentifierStart]
11220  * 0x005f ['_', IdentifierStart and
11221  * UnicodeConnectorPunctuation]
11222  *
11223  * UnicodeCombiningMark has no code points <= 0x7f.
11224  *
11225  * The matching code reuses the "identifier start" tables, and then
11226  * consults a separate range set for characters in "identifier part"
11227  * but not in "identifier start". These can be extracted with the
11228  * "tools/extract_chars.py" script.
11229  *
11230  * UnicodeCombiningMark -> categories Mn, Mc
11231  * UnicodeDigit -> categories Nd
11232  * UnicodeConnectorPunctuation -> categories Pc
11233  */
11234 
11235  /* ASCII (and EOF) fast path -- quick accept and reject */
11236  if (cp <= 0x7fL) {
11237 #if defined(DUK_USE_IDCHAR_FASTPATH)
11238  return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
11239 #else
11240  if ((cp >= 'a' && cp <= 'z') ||
11241  (cp >= 'A' && cp <= 'Z') ||
11242  (cp >= '0' && cp <= '9') ||
11243  cp == '_' || cp == '$') {
11244  return 1;
11245  }
11246  return 0;
11247 #endif
11248  }
11249 
11250  /* Non-ASCII slow path (range-by-range linear comparison), very slow */
11251 
11252 #if defined(DUK_USE_SOURCE_NONBMP)
11253  if (duk__uni_range_match(duk_unicode_ids_noa,
11254  sizeof(duk_unicode_ids_noa),
11255  (duk_codepoint_t) cp) ||
11256  duk__uni_range_match(duk_unicode_idp_m_ids_noa,
11257  sizeof(duk_unicode_idp_m_ids_noa),
11258  (duk_codepoint_t) cp)) {
11259  return 1;
11260  }
11261  return 0;
11262 #else
11263  if (cp < 0x10000L) {
11264  if (duk__uni_range_match(duk_unicode_ids_noabmp,
11265  sizeof(duk_unicode_ids_noabmp),
11266  (duk_codepoint_t) cp) ||
11267  duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
11268  sizeof(duk_unicode_idp_m_ids_noabmp),
11269  (duk_codepoint_t) cp)) {
11270  return 1;
11271  }
11272  return 0;
11273  } else {
11274  /* without explicit non-BMP support, assume non-BMP characters
11275  * are always accepted as identifier characters.
11276  */
11277  return 1;
11278  }
11279 #endif
11280 }
11281 
11282 /*
11283  * Unicode letter check.
11284  */
11285 
11286 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
11287  /*
11288  * Unicode letter is now taken to be the categories:
11289  *
11290  * Lu, Ll, Lt, Lm, Lo
11291  *
11292  * (Not sure if this is exactly correct.)
11293  *
11294  * The ASCII fast path consists of:
11295  *
11296  * 0x0041 ... 0x005a ['A' ... 'Z']
11297  * 0x0061 ... 0x007a ['a' ... 'z']
11298  */
11299 
11300  /* ASCII (and EOF) fast path -- quick accept and reject */
11301  if (cp <= 0x7fL) {
11302  if ((cp >= 'a' && cp <= 'z') ||
11303  (cp >= 'A' && cp <= 'Z')) {
11304  return 1;
11305  }
11306  return 0;
11307  }
11308 
11309  /* Non-ASCII slow path (range-by-range linear comparison), very slow */
11310 
11311 #if defined(DUK_USE_SOURCE_NONBMP)
11312  if (duk__uni_range_match(duk_unicode_ids_noa,
11313  sizeof(duk_unicode_ids_noa),
11314  (duk_codepoint_t) cp) &&
11315  !duk__uni_range_match(duk_unicode_ids_m_let_noa,
11316  sizeof(duk_unicode_ids_m_let_noa),
11317  (duk_codepoint_t) cp)) {
11318  return 1;
11319  }
11320  return 0;
11321 #else
11322  if (cp < 0x10000L) {
11323  if (duk__uni_range_match(duk_unicode_ids_noabmp,
11324  sizeof(duk_unicode_ids_noabmp),
11325  (duk_codepoint_t) cp) &&
11326  !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
11327  sizeof(duk_unicode_ids_m_let_noabmp),
11328  (duk_codepoint_t) cp)) {
11329  return 1;
11330  }
11331  return 0;
11332  } else {
11333  /* without explicit non-BMP support, assume non-BMP characters
11334  * are always accepted as letters.
11335  */
11336  return 1;
11337  }
11338 #endif
11339 }
11340 
11341 /*
11342  * Complex case conversion helper which decodes a bit-packed conversion
11343  * control stream generated by tools/extract_caseconv.py. The conversion
11344  * is very slow because it runs through the conversion data in a linear
11345  * fashion to save space (which is why ASCII characters have a special
11346  * fast path before arriving here).
11347  *
11348  * The particular bit counts etc have been determined experimentally to
11349  * be small but still sufficient, and must match the Python script
11350  * (tools/extract_caseconv.py).
11351  *
11352  * The return value is the case converted codepoint or -1 if the conversion
11353  * results in multiple characters (this is useful for regexp Canonicalization
11354  * operation). If 'buf' is not NULL, the result codepoint(s) are also
11355  * appended to the hbuffer.
11356  *
11357  * Context and locale specific rules must be checked before consulting
11358  * this function.
11359  */
11360 
11361 DUK_LOCAL
11362 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
11363  duk_bufwriter_ctx *bw,
11364  duk_codepoint_t cp,
11365  duk_bitdecoder_ctx *bd_ctx) {
11366  duk_small_int_t skip = 0;
11367  duk_small_int_t n;
11368  duk_small_int_t t;
11369  duk_small_int_t count;
11370  duk_codepoint_t tmp_cp;
11371  duk_codepoint_t start_i;
11372  duk_codepoint_t start_o;
11373 
11374  DUK_UNREF(thr);
11375  DUK_ASSERT(bd_ctx != NULL);
11376 
11377  DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
11378 
11379  /* range conversion with a "skip" */
11380  DUK_DDD(DUK_DDDPRINT("checking ranges"));
11381  for (;;) {
11382  skip++;
11383  n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
11384  if (n == 0x3f) {
11385  /* end marker */
11386  break;
11387  }
11388  DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
11389 
11390  while (n--) {
11391  start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11392  start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11393  count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
11394  DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
11395  (long) start_i, (long) start_o, (long) count, (long) skip));
11396 
11397  if (cp >= start_i) {
11398  tmp_cp = cp - start_i; /* always >= 0 */
11399  if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
11400  (tmp_cp % (duk_codepoint_t) skip) == 0) {
11401  DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
11402  cp = start_o + tmp_cp;
11403  goto single;
11404  }
11405  }
11406  }
11407  }
11408 
11409  /* 1:1 conversion */
11410  n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
11411  DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
11412  while (n--) {
11413  start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11414  start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11415  DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
11416  if (cp == start_i) {
11417  DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
11418  cp = start_o;
11419  goto single;
11420  }
11421  }
11422 
11423  /* complex, multicharacter conversion */
11424  n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
11425  DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
11426  while (n--) {
11427  start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11428  t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
11429  DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
11430  if (cp == start_i) {
11431  DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
11432  if (bw != NULL) {
11433  while (t--) {
11434  tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
11435  DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
11436  }
11437  }
11438  return -1;
11439  } else {
11440  while (t--) {
11441  (void) duk_bd_decode(bd_ctx, 16);
11442  }
11443  }
11444  }
11445 
11446  /* default: no change */
11447  DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
11448  /* fall through */
11449 
11450  single:
11451  if (bw != NULL) {
11452  DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
11453  }
11454  return cp;
11455 }
11456 
11457 /*
11458  * Case conversion helper, with context/local sensitivity.
11459  * For proper case conversion, one needs to know the character
11460  * and the preceding and following characters, as well as
11461  * locale/language.
11462  */
11463 
11464 /* XXX: add 'language' argument when locale/language sensitive rule
11465  * support added.
11466  */
11467 DUK_LOCAL
11468 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
11469  duk_bufwriter_ctx *bw,
11470  duk_codepoint_t cp,
11471  duk_codepoint_t prev,
11472  duk_codepoint_t next,
11473  duk_bool_t uppercase) {
11474  duk_bitdecoder_ctx bd_ctx;
11475 
11476  /* fast path for ASCII */
11477  if (cp < 0x80L) {
11478  /* XXX: there are language sensitive rules for the ASCII range.
11479  * If/when language/locale support is implemented, they need to
11480  * be implemented here for the fast path. There are no context
11481  * sensitive rules for ASCII range.
11482  */
11483 
11484  if (uppercase) {
11485  if (cp >= 'a' && cp <= 'z') {
11486  cp = cp - 'a' + 'A';
11487  }
11488  } else {
11489  if (cp >= 'A' && cp <= 'Z') {
11490  cp = cp - 'A' + 'a';
11491  }
11492  }
11493 
11494  if (bw != NULL) {
11495  DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
11496  }
11497  return cp;
11498  }
11499 
11500  /* context and locale specific rules which cannot currently be represented
11501  * in the caseconv bitstream: hardcoded rules in C
11502  */
11503  if (uppercase) {
11504  /* XXX: turkish / azeri */
11505  } else {
11506  /*
11507  * Final sigma context specific rule. This is a rather tricky
11508  * rule and this handling is probably not 100% correct now.
11509  * The rule is not locale/language specific so it is supported.
11510  */
11511 
11512  if (cp == 0x03a3L && /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
11513  duk_unicode_is_letter(prev) && /* prev exists and is not a letter */
11514  !duk_unicode_is_letter(next)) { /* next does not exist or next is not a letter */
11515  /* Capital sigma occurred at "end of word", lowercase to
11516  * U+03C2 = GREEK SMALL LETTER FINAL SIGMA. Otherwise
11517  * fall through and let the normal rules lowercase it to
11518  * U+03C3 = GREEK SMALL LETTER SIGMA.
11519  */
11520  cp = 0x03c2L;
11521  goto singlechar;
11522  }
11523 
11524  /* XXX: lithuanian not implemented */
11525  /* XXX: lithuanian, explicit dot rules */
11526  /* XXX: turkish / azeri, lowercase rules */
11527  }
11528 
11529  /* 1:1 or special conversions, but not locale/context specific: script generated rules */
11530  DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
11531  if (uppercase) {
11532  bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
11533  bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
11534  } else {
11535  bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
11536  bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
11537  }
11538  return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
11539 
11540  singlechar:
11541  if (bw != NULL) {
11542  DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
11543  }
11544  return cp;
11545 
11546  /* unused now, not needed until Turkish/Azeri */
11547 #if 0
11548  nochar:
11549  return -1;
11550 #endif
11551 }
11552 
11553 /*
11554  * Replace valstack top with case converted version.
11555  */
11556 
11557 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_small_int_t uppercase) {
11558  duk_context *ctx = (duk_context *) thr;
11559  duk_hstring *h_input;
11560  duk_bufwriter_ctx bw_alloc;
11561  duk_bufwriter_ctx *bw;
11562  const duk_uint8_t *p, *p_start, *p_end;
11563  duk_codepoint_t prev, curr, next;
11564 
11565  h_input = duk_require_hstring(ctx, -1); /* Accept symbols. */
11566  DUK_ASSERT(h_input != NULL);
11567 
11568  bw = &bw_alloc;
11569  DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
11570 
11571  /* [ ... input buffer ] */
11572 
11573  p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
11574  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
11575  p = p_start;
11576 
11577  prev = -1; DUK_UNREF(prev);
11578  curr = -1;
11579  next = -1;
11580  for (;;) {
11581  prev = curr;
11582  curr = next;
11583  next = -1;
11584  if (p < p_end) {
11585  next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
11586  } else {
11587  /* end of input and last char has been processed */
11588  if (curr < 0) {
11589  break;
11590  }
11591  }
11592 
11593  /* on first round, skip */
11594  if (curr >= 0) {
11595  /* XXX: could add a fast path to process chunks of input codepoints,
11596  * but relative benefit would be quite small.
11597  */
11598 
11599  /* Ensure space for maximum multi-character result; estimate is overkill. */
11600  DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
11601 
11602  duk__case_transform_helper(thr,
11603  bw,
11604  (duk_codepoint_t) curr,
11605  prev,
11606  next,
11607  uppercase);
11608  }
11609  }
11610 
11611  DUK_BW_COMPACT(thr, bw);
11612  (void) duk_buffer_to_string(ctx, -1); /* Safe, output is encoded. */
11613  /* invalidates h_buf pointer */
11614  duk_remove_m2(ctx);
11615 }
11616 
11617 #if defined(DUK_USE_REGEXP_SUPPORT)
11618 
11619 /*
11620  * Canonicalize() abstract operation needed for canonicalization of individual
11621  * codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
11622  * Note that codepoints are canonicalized one character at a time, so no context
11623  * specific rules can apply. Locale specific rules can apply, though.
11624  */
11625 
11626 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
11627 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
11628  /* Fast canonicalization lookup at the cost of 128kB footprint. */
11629  DUK_ASSERT(cp >= 0);
11630  DUK_UNREF(thr);
11631  if (DUK_LIKELY(cp < 0x10000L)) {
11632  return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
11633  }
11634  return cp;
11635 #else /* DUK_USE_REGEXP_CANON_WORKAROUND */
11636  duk_codepoint_t y;
11637 
11638  y = duk__case_transform_helper(thr,
11639  NULL, /* NULL is allowed, no output */
11640  cp, /* curr char */
11641  -1, /* prev char */
11642  -1, /* next char */
11643  1); /* uppercase */
11644 
11645  if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
11646  /* multiple codepoint conversion or non-ASCII mapped to ASCII
11647  * --> leave as is.
11648  */
11649  return cp;
11650  }
11651 
11652  return y;
11653 #endif /* DUK_USE_REGEXP_CANON_WORKAROUND */
11654 }
11655 
11656 /*
11657  * E5 Section 15.10.2.6 "IsWordChar" abstract operation. Assume
11658  * x < 0 for characters read outside the string.
11659  */
11660 
11661 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
11662  /*
11663  * Note: the description in E5 Section 15.10.2.6 has a typo, it
11664  * contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
11665  */
11666  if ((x >= '0' && x <= '9') ||
11667  (x >= 'a' && x <= 'z') ||
11668  (x >= 'A' && x <= 'Z') ||
11669  (x == '_')) {
11670  return 1;
11671  }
11672  return 0;
11673 }
11674 
11675 /*
11676  * Regexp range tables
11677  */
11678 
11679 /* exposed because lexer needs these too */
11680 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
11681  (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11682 };
11683 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
11684  (duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
11685  (duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
11686  (duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
11687  (duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
11688  (duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
11689  (duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
11690  (duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
11691  (duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
11692  (duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
11693  (duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
11694  (duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
11695 };
11696 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
11697  (duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
11698  (duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
11699  (duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
11700  (duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
11701 };
11702 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
11703  (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11704  (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
11705 };
11706 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
11707  (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
11708  (duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
11709  (duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
11710  (duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
11711  (duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
11712  (duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
11713  (duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
11714  (duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
11715  (duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
11716  (duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
11717  (duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
11718  (duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
11719 };
11720 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
11721  (duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
11722  (duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
11723  (duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
11724  (duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
11725  (duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
11726 };
11727 
11728 #endif /* DUK_USE_REGEXP_SUPPORT */
11729 /*
11730  * Misc util stuff
11731  */
11732 
11733 /* #include duk_internal.h -> already included */
11734 
11735 /*
11736  * Lowercase digits for radix values 2 to 36. Also doubles as lowercase
11737  * hex nybble table.
11738  */
11739 
11740 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
11741  DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
11742  DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
11743  DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
11744  DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
11745  DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
11746  DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
11747  DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
11748  DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
11749  DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
11750 };
11751 
11752 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
11753  DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
11754  DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
11755  DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
11756  DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
11757 };
11758 
11759 /*
11760  * Table for hex decoding ASCII hex digits
11761  */
11762 
11763 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
11764  /* -1 if invalid */
11765  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11766  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11767  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11768  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11769  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11770  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11771  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11772  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11773  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11774  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11775  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11776  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11777  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11778  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11779  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11780  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11781 };
11782 
11783 #if defined(DUK_USE_HEX_FASTPATH)
11784 /* Preshifted << 4. Must use 16-bit entry to allow negative value signaling. */
11785 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
11786  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0f */
11787  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1f */
11788  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2f */
11789  0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, /* 0x30-0x3f */
11790  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4f */
11791  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5f */
11792  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x60-0x6f */
11793  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x70-0x7f */
11794  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80-0x8f */
11795  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90-0x9f */
11796  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0-0xaf */
11797  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0-0xbf */
11798  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0-0xcf */
11799  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0-0xdf */
11800  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0-0xef */
11801  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0-0xff */
11802 };
11803 #endif
11804 
11805 /*
11806  * Table for hex encoding bytes
11807  */
11808 
11809 #if defined(DUK_USE_HEX_FASTPATH)
11810 /* Lookup to encode one byte directly into 2 characters:
11811  *
11812  * def genhextab(bswap):
11813  * for i in xrange(256):
11814  * t = chr(i).encode('hex')
11815  * if bswap:
11816  * t = t[1] + t[0]
11817  * print('0x' + t.encode('hex') + 'U')
11818  * print('big endian'); genhextab(False)
11819  * print('little endian'); genhextab(True)
11820 */
11821 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
11822 #if defined(DUK_USE_INTEGER_BE)
11823  0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
11824  0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
11825  0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
11826  0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
11827  0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
11828  0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
11829  0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
11830  0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
11831  0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
11832  0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
11833  0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
11834  0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
11835  0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
11836  0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
11837  0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
11838  0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
11839  0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
11840  0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
11841  0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
11842  0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
11843  0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
11844  0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
11845  0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
11846  0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
11847  0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
11848  0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
11849  0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
11850  0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
11851  0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
11852  0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
11853  0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
11854  0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
11855 #else /* DUK_USE_INTEGER_BE */
11856  0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
11857  0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
11858  0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
11859  0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
11860  0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
11861  0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
11862  0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
11863  0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
11864  0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
11865  0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
11866  0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
11867  0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
11868  0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
11869  0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
11870  0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
11871  0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
11872  0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
11873  0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
11874  0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
11875  0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
11876  0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
11877  0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
11878  0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
11879  0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
11880  0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
11881  0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
11882  0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
11883  0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
11884  0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
11885  0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
11886  0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
11887  0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
11888 #endif /* DUK_USE_INTEGER_BE */
11889 };
11890 #endif /* DUK_USE_HEX_FASTPATH */
11891 
11892 /*
11893  * Table for base-64 encoding
11894  */
11895 
11896 #if defined(DUK_USE_BASE64_FASTPATH)
11897 DUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {
11898  0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, /* A...P */
11899  0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, /* Q...f */
11900  0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, /* g...v */
11901  0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f /* w.../ */
11902 };
11903 #endif /* DUK_USE_BASE64_FASTPATH */
11904 
11905 /*
11906  * Table for base-64 decoding
11907  */
11908 
11909 #if defined(DUK_USE_BASE64_FASTPATH)
11910 DUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {
11911  /* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */
11912  -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, /* 0x00...0x0f */
11913  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10...0x1f */
11914  -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20...0x2f */
11915  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1, /* 0x30...0x3f */
11916  -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40...0x4f */
11917  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50...0x5f */
11918  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60...0x6f */
11919  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 0x70...0x7f */
11920  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x80...0x8f */
11921  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x90...0x9f */
11922  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa0...0xaf */
11923  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb0...0xbf */
11924  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc0...0xcf */
11925  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd0...0xdf */
11926  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe0...0xef */
11927  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xf0...0xff */
11928 };
11929 #endif /* DUK_USE_BASE64_FASTPATH */
11930 
11931 /*
11932  * Arbitrary byteswap for potentially unaligned values
11933  *
11934  * Used to byteswap pointers e.g. in debugger code.
11935  */
11936 
11937 #if defined(DUK_USE_DEBUGGER_SUPPORT) /* For now only needed by the debugger. */
11938 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
11939  duk_uint8_t tmp;
11940  duk_uint8_t *q = p + len - 1;
11941 
11942  while (p - q < 0) {
11943  tmp = *p;
11944  *p = *q;
11945  *q = tmp;
11946  p++;
11947  q--;
11948  }
11949 }
11950 #endif
11951 
11952 /*
11953  * Miscellaneous coercion / clamping helpers.
11954  */
11955 
11956 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
11957  * negative zero), and if so, return a duk_int32_t.
11958  * For compiler use: don't allow negative zero as it will cause trouble with
11959  * LDINT+LDINTX, positive zero is OK.
11960  */
11961 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
11962  duk_int32_t t;
11963 
11964  t = (duk_int32_t) x;
11965  if (!((duk_double_t) t == x)) {
11966  return 0;
11967  }
11968  if (t == 0) {
11969  duk_double_union du;
11970  du.d = x;
11971  if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
11972  return 0;
11973  }
11974  }
11975  *ival = t;
11976  return 1;
11977 }
11978 
11979 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
11980  * so, return a duk_int32_t.
11981  */
11982 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
11983  duk_int32_t t;
11984 
11985  t = (duk_int32_t) x;
11986  if (!((duk_double_t) t == x)) {
11987  return 0;
11988  }
11989  *ival = t;
11990  return 1;
11991 }
11992 
11993 /*
11994  * IEEE double checks
11995  */
11996 
11997 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
11998  duk_double_union du;
11999  du.d = x;
12000  return DUK_DBLUNION_IS_ANYINF(&du);
12001 }
12002 
12003 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
12004  duk_double_union du;
12005  du.d = x;
12006  return DUK_DBLUNION_IS_POSINF(&du);
12007 }
12008 
12009 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
12010  duk_double_union du;
12011  du.d = x;
12012  return DUK_DBLUNION_IS_NEGINF(&du);
12013 }
12014 
12015 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
12016  duk_double_union du;
12017  du.d = x;
12018  /* Assumes we're dealing with a Duktape internal NaN which is
12019  * NaN normalized if duk_tval requires it.
12020  */
12021  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
12022  return DUK_DBLUNION_IS_NAN(&du);
12023 }
12024 
12025 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
12026  duk_double_union du;
12027  du.d = x;
12028  /* Assumes we're dealing with a Duktape internal NaN which is
12029  * NaN normalized if duk_tval requires it.
12030  */
12031  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
12032  return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
12033 }
12034 
12035 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
12036  duk_double_union du;
12037  du.d = x;
12038  /* If exponent is 0x7FF the argument is either a NaN or an
12039  * infinity. We don't need to check any other fields.
12040  */
12041 #if defined(DUK_USE_64BIT_OPS)
12042 #if defined(DUK_USE_DOUBLE_ME)
12043  return (du.ull[DUK_DBL_IDX_ULL0] & 0x000000007ff00000ULL) == 0x000000007ff00000ULL;
12044 #else
12045  return (du.ull[DUK_DBL_IDX_ULL0] & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL;
12046 #endif
12047 #else
12048  return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
12049 #endif
12050 }
12051 
12052 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
12053  duk_double_union du;
12054 #if defined(DUK_USE_64BIT_OPS)
12055  duk_uint64_t t;
12056 #else
12057  duk_uint32_t t;
12058 #endif
12059  du.d = x;
12060 #if defined(DUK_USE_64BIT_OPS)
12061 #if defined(DUK_USE_DOUBLE_ME)
12062  t = du.ull[DUK_DBL_IDX_ULL0] & 0x000000007ff00000ULL;
12063  if (t == 0x0000000000000000ULL) {
12064  t = du.ull[DUK_DBL_IDX_ULL0] & 0x0000000080000000ULL;
12065  return t == 0;
12066  }
12067  if (t == 0x000000007ff00000UL) {
12068  return 1;
12069  }
12070 #else
12071  t = du.ull[DUK_DBL_IDX_ULL0] & 0x7ff0000000000000ULL;
12072  if (t == 0x0000000000000000ULL) {
12073  t = du.ull[DUK_DBL_IDX_ULL0] & 0x8000000000000000ULL;
12074  return t == 0;
12075  }
12076  if (t == 0x7ff0000000000000ULL) {
12077  return 1;
12078  }
12079 #endif
12080 #else
12081  t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
12082  if (t == 0x00000000UL) {
12083  return DUK_DBLUNION_IS_ANYZERO(&du);
12084  }
12085  if (t == 0x7ff00000UL) {
12086  return 1;
12087  }
12088 #endif
12089  return 0;
12090 }
12091 
12092 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
12093  duk_double_union du;
12094  du.d = x;
12095  return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
12096 }
12097 
12098 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
12099  /* XXX: optimize */
12100  duk_small_int_t s = duk_double_signbit(x);
12101  x = DUK_FLOOR(DUK_FABS(x)); /* truncate towards zero */
12102  if (s) {
12103  x = -x;
12104  }
12105  return x;
12106 }
12107 
12108 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
12109  duk_double_union du1;
12110  duk_double_union du2;
12111  du1.d = x;
12112  du2.d = y;
12113 
12114  return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
12115 }
12116 
12117 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
12118  /* Doesn't replicate fmin() behavior exactly: for fmin() if one
12119  * argument is a NaN, the other argument should be returned.
12120  * Duktape doesn't rely on this behavior so the replacement can
12121  * be simplified.
12122  */
12123  return (x < y ? x : y);
12124 }
12125 
12126 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
12127  /* Doesn't replicate fmax() behavior exactly: for fmax() if one
12128  * argument is a NaN, the other argument should be returned.
12129  * Duktape doesn't rely on this behavior so the replacement can
12130  * be simplified.
12131  */
12132  return (x > y ? x : y);
12133 }
12134 /*
12135  * Round a number upwards to a prime (not usually the nearest one).
12136  *
12137  * Uses a table of successive 32-bit primes whose ratio is roughly
12138  * constant. This keeps the relative upwards 'rounding error' bounded
12139  * and the data size small. A simple 'predict-correct' compression is
12140  * used to compress primes to one byte per prime. See genhashsizes.py
12141  * for details.
12142  *
12143  * The minimum prime returned here must be coordinated with the possible
12144  * probe sequence steps in duk_hobject and duk_heap stringtable.
12145  */
12146 
12147 /* #include duk_internal.h -> already included */
12148 
12149 /* Awkward inclusion condition: drop out of compilation if not needed by any
12150  * call site: object hash part or probing stringtable.
12151  */
12152 #if defined(DUK_USE_HOBJECT_HASH_PART) || defined(DUK_USE_STRTAB_PROBE)
12153 
12154 /* hash size ratio goal, must match genhashsizes.py */
12155 #define DUK__HASH_SIZE_RATIO 1177 /* floor(1.15 * (1 << 10)) */
12156 
12157 /* prediction corrections for prime list (see genhashsizes.py) */
12158 DUK_LOCAL const duk_int8_t duk__hash_size_corrections[] = {
12159  17, /* minimum prime */
12160  4, 3, 4, 1, 4, 1, 1, 2, 2, 2, 2, 1, 6, 6, 9, 5, 1, 2, 2, 5, 1, 3, 3, 3,
12161  5, 4, 4, 2, 4, 8, 3, 4, 23, 2, 4, 7, 8, 11, 2, 12, 15, 10, 1, 1, 5, 1, 5,
12162  8, 9, 17, 14, 10, 7, 5, 2, 46, 21, 1, 9, 9, 4, 4, 10, 23, 36, 6, 20, 29,
12163  18, 6, 19, 21, 16, 11, 5, 5, 48, 9, 1, 39, 14, 8, 4, 29, 9, 1, 15, 48, 12,
12164  22, 6, 15, 27, 4, 2, 17, 28, 8, 9, 4, 5, 8, 3, 3, 8, 37, 11, 15, 8, 30,
12165  43, 6, 33, 41, 5, 20, 32, 41, 38, 24, 77, 14, 19, 11, 4, 35, 18, 19, 41,
12166  10, 23, 16, 9, 2,
12167  -1
12168 };
12169 
12170 /* probe steps (see genhashsizes.py), currently assumed to be 32 entries long
12171  * (DUK_UTIL_GET_HASH_PROBE_STEP macro).
12172  */
12173 DUK_INTERNAL duk_uint8_t duk_util_probe_steps[32] = {
12174  2, 3, 5, 7, 11, 13, 19, 31, 41, 47, 59, 67, 73, 79, 89, 101, 103, 107,
12175  109, 127, 137, 139, 149, 157, 163, 167, 173, 181, 191, 193, 197, 199
12176 };
12177 
12178 DUK_INTERNAL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size) {
12179  const duk_int8_t *p = duk__hash_size_corrections;
12180  duk_uint32_t curr;
12181 
12182  curr = (duk_uint32_t) *p++;
12183  for (;;) {
12184  duk_small_int_t t = (duk_small_int_t) *p++;
12185  if (t < 0) {
12186  /* may happen if size is very close to 2^32-1 */
12187  break;
12188  }
12189 
12190  /* prediction: portable variant using doubles if 64-bit values not available */
12191 #if defined(DUK_USE_64BIT_OPS)
12192  curr = (duk_uint32_t) ((((duk_uint64_t) curr) * ((duk_uint64_t) DUK__HASH_SIZE_RATIO)) >> 10);
12193 #else
12194  /* 32-bit x 11-bit = 43-bit, fits accurately into a double */
12195  curr = (duk_uint32_t) DUK_FLOOR(((double) curr) * ((double) DUK__HASH_SIZE_RATIO) / 1024.0);
12196 #endif
12197 
12198  /* correction */
12199  curr += t;
12200 
12201  DUK_DDD(DUK_DDDPRINT("size=%ld, curr=%ld", (long) size, (long) curr));
12202 
12203  if (curr >= size) {
12204  return curr;
12205  }
12206  }
12207  return 0;
12208 }
12209 
12210 #endif /* DUK_USE_HOBJECT_HASH_PART || DUK_USE_STRTAB_PROBE */
12211 
12212 /* automatic undefs */
12213 #undef DUK__HASH_SIZE_RATIO
12214 /*
12215  * Hobject Ecmascript [[Class]].
12216  */
12217 
12218 /* #include duk_internal.h -> already included */
12219 
12220 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
12221 #error constant too large
12222 #endif
12223 #if (DUK_STRIDX_ARRAY > 255)
12224 #error constant too large
12225 #endif
12226 #if (DUK_STRIDX_UC_BOOLEAN > 255)
12227 #error constant too large
12228 #endif
12229 #if (DUK_STRIDX_DATE > 255)
12230 #error constant too large
12231 #endif
12232 #if (DUK_STRIDX_UC_ERROR > 255)
12233 #error constant too large
12234 #endif
12235 #if (DUK_STRIDX_UC_FUNCTION > 255)
12236 #error constant too large
12237 #endif
12238 #if (DUK_STRIDX_JSON > 255)
12239 #error constant too large
12240 #endif
12241 #if (DUK_STRIDX_MATH > 255)
12242 #error constant too large
12243 #endif
12244 #if (DUK_STRIDX_UC_NUMBER > 255)
12245 #error constant too large
12246 #endif
12247 #if (DUK_STRIDX_UC_OBJECT > 255)
12248 #error constant too large
12249 #endif
12250 #if (DUK_STRIDX_REG_EXP > 255)
12251 #error constant too large
12252 #endif
12253 #if (DUK_STRIDX_UC_STRING > 255)
12254 #error constant too large
12255 #endif
12256 #if (DUK_STRIDX_GLOBAL > 255)
12257 #error constant too large
12258 #endif
12259 #if (DUK_STRIDX_OBJ_ENV > 255)
12260 #error constant too large
12261 #endif
12262 #if (DUK_STRIDX_DEC_ENV > 255)
12263 #error constant too large
12264 #endif
12265 #if (DUK_STRIDX_UC_POINTER > 255)
12266 #error constant too large
12267 #endif
12268 #if (DUK_STRIDX_UC_THREAD > 255)
12269 #error constant too large
12270 #endif
12271 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
12272 #error constant too large
12273 #endif
12274 #if (DUK_STRIDX_DATA_VIEW > 255)
12275 #error constant too large
12276 #endif
12277 #if (DUK_STRIDX_INT8_ARRAY > 255)
12278 #error constant too large
12279 #endif
12280 #if (DUK_STRIDX_UINT8_ARRAY > 255)
12281 #error constant too large
12282 #endif
12283 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
12284 #error constant too large
12285 #endif
12286 #if (DUK_STRIDX_INT16_ARRAY > 255)
12287 #error constant too large
12288 #endif
12289 #if (DUK_STRIDX_UINT16_ARRAY > 255)
12290 #error constant too large
12291 #endif
12292 #if (DUK_STRIDX_INT32_ARRAY > 255)
12293 #error constant too large
12294 #endif
12295 #if (DUK_STRIDX_UINT32_ARRAY > 255)
12296 #error constant too large
12297 #endif
12298 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
12299 #error constant too large
12300 #endif
12301 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
12302 #error constant too large
12303 #endif
12304 #if (DUK_STRIDX_EMPTY_STRING > 255)
12305 #error constant too large
12306 #endif
12307 
12308 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
12309 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
12310  DUK_STRIDX_EMPTY_STRING, /* NONE, intentionally empty */
12311  DUK_STRIDX_UC_OBJECT,
12312  DUK_STRIDX_ARRAY,
12313  DUK_STRIDX_UC_FUNCTION,
12314  DUK_STRIDX_UC_ARGUMENTS,
12315  DUK_STRIDX_UC_BOOLEAN,
12316  DUK_STRIDX_DATE,
12317  DUK_STRIDX_UC_ERROR,
12318  DUK_STRIDX_JSON,
12319  DUK_STRIDX_MATH,
12320  DUK_STRIDX_UC_NUMBER,
12321  DUK_STRIDX_REG_EXP,
12322  DUK_STRIDX_UC_STRING,
12323  DUK_STRIDX_GLOBAL,
12324  DUK_STRIDX_UC_SYMBOL,
12325  DUK_STRIDX_OBJ_ENV,
12326  DUK_STRIDX_DEC_ENV,
12327  DUK_STRIDX_UC_POINTER,
12328  DUK_STRIDX_UC_THREAD,
12329  DUK_STRIDX_ARRAY_BUFFER,
12330  DUK_STRIDX_DATA_VIEW,
12331  DUK_STRIDX_INT8_ARRAY,
12332  DUK_STRIDX_UINT8_ARRAY,
12333  DUK_STRIDX_UINT8_CLAMPED_ARRAY,
12334  DUK_STRIDX_INT16_ARRAY,
12335  DUK_STRIDX_UINT16_ARRAY,
12336  DUK_STRIDX_INT32_ARRAY,
12337  DUK_STRIDX_UINT32_ARRAY,
12338  DUK_STRIDX_FLOAT32_ARRAY,
12339  DUK_STRIDX_FLOAT64_ARRAY,
12340  DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
12341  DUK_STRIDX_EMPTY_STRING, /* UNUSED, intentionally empty */
12342 };
12343 /*
12344  * Default allocation functions.
12345  *
12346  * Assumes behavior such as malloc allowing zero size, yielding
12347  * a NULL or a unique pointer which is a no-op for free.
12348  */
12349 
12350 /* #include duk_internal.h -> already included */
12351 
12352 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
12353 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
12354  void *res;
12355  DUK_UNREF(udata);
12356  res = DUK_ANSI_MALLOC(size);
12357  DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
12358  (unsigned long) size, (void *) res));
12359  return res;
12360 }
12361 
12362 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
12363  void *res;
12364  DUK_UNREF(udata);
12365  res = DUK_ANSI_REALLOC(ptr, newsize);
12366  DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
12367  (void *) ptr, (unsigned long) newsize, (void *) res));
12368  return res;
12369 }
12370 
12371 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
12372  DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
12373  DUK_UNREF(udata);
12374  DUK_ANSI_FREE(ptr);
12375 }
12376 #endif /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
12377 /*
12378  * Buffer
12379  */
12380 
12381 /* #include duk_internal.h -> already included */
12382 
12383 DUK_EXTERNAL void *duk_resize_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t new_size) {
12384  duk_hthread *thr = (duk_hthread *) ctx;
12386 
12387  DUK_ASSERT_CTX_VALID(ctx);
12388 
12389  h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, idx);
12390  DUK_ASSERT(h != NULL);
12391 
12392  if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
12393  DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
12394  }
12395 
12396  /* maximum size check is handled by callee */
12397  duk_hbuffer_resize(thr, h, new_size);
12398 
12399  return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
12400 }
12401 
12402 DUK_EXTERNAL void *duk_steal_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size) {
12403  duk_hthread *thr = (duk_hthread *) ctx;
12405  void *ptr;
12406  duk_size_t sz;
12407 
12408  DUK_ASSERT(ctx != NULL);
12409 
12410  h = (duk_hbuffer_dynamic *) duk_require_hbuffer(ctx, idx);
12411  DUK_ASSERT(h != NULL);
12412 
12413  if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
12414  DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
12415  }
12416 
12417  /* Forget the previous allocation, setting size to 0 and alloc to
12418  * NULL. Caller is responsible for freeing the previous allocation.
12419  * Getting the allocation and clearing it is done in the same API
12420  * call to avoid any chance of a realloc.
12421  */
12422  ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
12423  sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
12424  if (out_size) {
12425  *out_size = sz;
12426  }
12427  DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
12428  DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
12429 
12430  return ptr;
12431 }
12432 
12433 DUK_EXTERNAL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void *ptr, duk_size_t len) {
12434  duk_hthread *thr = (duk_hthread *) ctx;
12436 
12437  DUK_ASSERT(ctx != NULL);
12438 
12439  h = (duk_hbuffer_external *) duk_require_hbuffer(ctx, idx);
12440  DUK_ASSERT(h != NULL);
12441 
12442  if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
12443  DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
12444  }
12445  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
12446 
12447  DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
12448  DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
12449 }
12450 /*
12451  * Bytecode dump/load
12452  *
12453  * The bytecode load primitive is more important performance-wise than the
12454  * dump primitive.
12455  *
12456  * Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
12457  * memory safe for invalid arguments - caller beware! There's little point
12458  * in trying to achieve memory safety unless bytecode instructions are also
12459  * validated which is not easy to do with indirect register references etc.
12460  */
12461 
12462 /* #include duk_internal.h -> already included */
12463 
12464 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
12465 
12466 #define DUK__SER_MARKER 0xff
12467 #define DUK__SER_VERSION 0x00
12468 #define DUK__SER_STRING 0x00
12469 #define DUK__SER_NUMBER 0x01
12470 #define DUK__BYTECODE_INITIAL_ALLOC 256
12471 
12472 /*
12473  * Dump/load helpers, xxx_raw() helpers do no buffer checks
12474  */
12475 
12476 DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_context *ctx, duk_uint8_t *p) {
12477  duk_uint32_t len;
12478 
12479  len = DUK_RAW_READ_U32_BE(p);
12480  duk_push_lstring(ctx, (const char *) p, len);
12481  p += len;
12482  return p;
12483 }
12484 
12485 DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_context *ctx, duk_uint8_t *p) {
12486  duk_uint32_t len;
12487  duk_uint8_t *buf;
12488 
12489  len = DUK_RAW_READ_U32_BE(p);
12490  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, (duk_size_t) len);
12491  DUK_ASSERT(buf != NULL);
12492  DUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);
12493  p += len;
12494  return p;
12495 }
12496 
12497 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
12498  duk_size_t len;
12499  duk_uint32_t tmp32;
12500 
12501  DUK_ASSERT(h != NULL);
12502 
12503  len = DUK_HSTRING_GET_BYTELEN(h);
12504  DUK_ASSERT(len <= 0xffffffffUL); /* string limits */
12505  tmp32 = (duk_uint32_t) len;
12506  DUK_RAW_WRITE_U32_BE(p, tmp32);
12507  DUK_MEMCPY((void *) p,
12508  (const void *) DUK_HSTRING_GET_DATA(h),
12509  len);
12510  p += len;
12511  return p;
12512 }
12513 
12514 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
12515  duk_size_t len;
12516  duk_uint32_t tmp32;
12517 
12518  DUK_ASSERT(thr != NULL);
12519  DUK_ASSERT(h != NULL);
12520  DUK_UNREF(thr);
12521 
12522  len = DUK_HBUFFER_GET_SIZE(h);
12523  DUK_ASSERT(len <= 0xffffffffUL); /* buffer limits */
12524  tmp32 = (duk_uint32_t) len;
12525  DUK_RAW_WRITE_U32_BE(p, tmp32);
12526  DUK_MEMCPY((void *) p,
12527  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
12528  len);
12529  p += len;
12530  return p;
12531 }
12532 
12533 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) {
12534  duk_hstring *h_str;
12535  duk_tval *tv;
12536 
12537  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
12538  if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
12539  h_str = DUK_TVAL_GET_STRING(tv);
12540  DUK_ASSERT(h_str != NULL);
12541  } else {
12542  h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
12543  DUK_ASSERT(h_str != NULL);
12544  }
12545  DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
12546  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(h_str), p);
12547  p = duk__dump_hstring_raw(p, h_str);
12548  return p;
12549 }
12550 
12551 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) {
12552  duk_tval *tv;
12553 
12554  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
12555  if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
12556  duk_hbuffer *h_buf;
12557  h_buf = DUK_TVAL_GET_BUFFER(tv);
12558  DUK_ASSERT(h_buf != NULL);
12559  DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
12560  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HBUFFER_GET_SIZE(h_buf), p);
12561  p = duk__dump_hbuffer_raw(thr, p, h_buf);
12562  } else {
12563  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
12564  DUK_RAW_WRITE_U32_BE(p, 0);
12565  }
12566  return p;
12567 }
12568 
12569 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) {
12570  duk_tval *tv;
12571  duk_uint32_t val;
12572 
12573  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
12574  if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
12575  val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
12576  } else {
12577  val = def_value;
12578  }
12579  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
12580  DUK_RAW_WRITE_U32_BE(p, val);
12581  return p;
12582 }
12583 
12584 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
12585  duk_tval *tv;
12586 
12587  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
12588  if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
12589  duk_hobject *h;
12590  duk_uint_fast32_t i;
12591 
12592  h = DUK_TVAL_GET_OBJECT(tv);
12593  DUK_ASSERT(h != NULL);
12594 
12595  /* We know _Varmap only has own properties so walk property
12596  * table directly. We also know _Varmap is dense and all
12597  * values are numbers; assert for these. GC and finalizers
12598  * shouldn't affect _Varmap so side effects should be fine.
12599  */
12600  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
12601  duk_hstring *key;
12602  duk_tval *tv_val;
12603  duk_uint32_t val;
12604 
12605  key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
12606  DUK_ASSERT(key != NULL); /* _Varmap is dense */
12607  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
12608  tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
12609  DUK_ASSERT(tv_val != NULL);
12610  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val)); /* known to be number; in fact an integer */
12611 #if defined(DUK_USE_FASTINT)
12612  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
12613  DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val)); /* known to be 32-bit */
12614  val = DUK_TVAL_GET_FASTINT_U32(tv_val);
12615 #else
12616  val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
12617 #endif
12618 
12619  DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
12620  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(key) + 4, p);
12621  p = duk__dump_hstring_raw(p, key);
12622  DUK_RAW_WRITE_U32_BE(p, val);
12623  }
12624  }
12625  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
12626  DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Varmap */
12627  return p;
12628 }
12629 
12630 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
12631  duk_tval *tv;
12632 
12633  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
12634  if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
12635  duk_hobject *h;
12636  duk_uint_fast32_t i;
12637 
12638  h = DUK_TVAL_GET_OBJECT(tv);
12639  DUK_ASSERT(h != NULL);
12640 
12641  /* We know _Formals is dense and all entries will be in the
12642  * array part. GC and finalizers shouldn't affect _Formals
12643  * so side effects should be fine.
12644  */
12645  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
12646  duk_tval *tv_val;
12647  duk_hstring *varname;
12648 
12649  tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, h, i);
12650  DUK_ASSERT(tv_val != NULL);
12651  if (DUK_TVAL_IS_STRING(tv_val)) {
12652  /* Array is dense and contains only strings, but ASIZE may
12653  * be larger than used part and there are UNUSED entries.
12654  */
12655  varname = DUK_TVAL_GET_STRING(tv_val);
12656  DUK_ASSERT(varname != NULL);
12657  DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1); /* won't be confused with terminator */
12658 
12659  DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
12660  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4 + DUK_HSTRING_GET_BYTELEN(varname), p);
12661  p = duk__dump_hstring_raw(p, varname);
12662  }
12663  }
12664  } else {
12665  DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit empty list"));
12666  }
12667  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4, p);
12668  DUK_RAW_WRITE_U32_BE(p, 0); /* end of _Formals */
12669  return p;
12670 }
12671 
12672 static duk_uint8_t *duk__dump_func(duk_context *ctx, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
12673  duk_hthread *thr;
12674  duk_tval *tv, *tv_end;
12675  duk_instr_t *ins, *ins_end;
12676  duk_hobject **fn, **fn_end;
12677  duk_hstring *h_str;
12678  duk_uint32_t count_instr;
12679  duk_uint32_t tmp32;
12680  duk_uint16_t tmp16;
12681  duk_double_t d;
12682 
12683  thr = (duk_hthread *) ctx;
12684  DUK_UNREF(ctx);
12685  DUK_UNREF(thr);
12686 
12687  DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
12688  "consts=[%p,%p[ (%ld bytes, %ld items), "
12689  "funcs=[%p,%p[ (%ld bytes, %ld items), "
12690  "code=[%p,%p[ (%ld bytes, %ld items)",
12691  (void *) func,
12692  (void *) p,
12693  (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
12694  (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
12695  (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
12696  (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
12697  (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
12698  (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
12699  (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
12700  (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
12701  (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
12702  (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
12703  (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
12704  (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
12705 
12706  DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL); /* ensures no overflow */
12707  count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
12708  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3 * 4 + 2 * 2 + 3 * 4 + count_instr * 4, p);
12709 
12710  /* Fixed header info. */
12711  tmp32 = count_instr;
12712  DUK_RAW_WRITE_U32_BE(p, tmp32);
12713  tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
12714  DUK_RAW_WRITE_U32_BE(p, tmp32);
12715  tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
12716  DUK_RAW_WRITE_U32_BE(p, tmp32);
12717  tmp16 = func->nregs;
12718  DUK_RAW_WRITE_U16_BE(p, tmp16);
12719  tmp16 = func->nargs;
12720  DUK_RAW_WRITE_U16_BE(p, tmp16);
12721 #if defined(DUK_USE_DEBUGGER_SUPPORT)
12722  tmp32 = func->start_line;
12723  DUK_RAW_WRITE_U32_BE(p, tmp32);
12724  tmp32 = func->end_line;
12725  DUK_RAW_WRITE_U32_BE(p, tmp32);
12726 #else
12727  DUK_RAW_WRITE_U32_BE(p, 0);
12728  DUK_RAW_WRITE_U32_BE(p, 0);
12729 #endif
12730  tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func); /* masks flags, only duk_hobject flags */
12731  DUK_RAW_WRITE_U32_BE(p, tmp32);
12732 
12733  /* Bytecode instructions: endian conversion needed unless
12734  * platform is big endian.
12735  */
12736  ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
12737  ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
12738  DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
12739 #if defined(DUK_USE_INTEGER_BE)
12740  DUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));
12741  p += (size_t) (ins_end - ins);
12742 #else
12743  while (ins != ins_end) {
12744  tmp32 = (duk_uint32_t) (*ins);
12745  DUK_RAW_WRITE_U32_BE(p, tmp32);
12746  ins++;
12747  }
12748 #endif
12749 
12750  /* Constants: variable size encoding. */
12751  tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
12752  tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
12753  while (tv != tv_end) {
12754  /* constants are strings or numbers now */
12755  DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
12756  DUK_TVAL_IS_NUMBER(tv));
12757 
12758  if (DUK_TVAL_IS_STRING(tv)) {
12759  h_str = DUK_TVAL_GET_STRING(tv);
12760  DUK_ASSERT(h_str != NULL);
12761  DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL); /* ensures no overflow */
12762  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 4 + DUK_HSTRING_GET_BYTELEN(h_str), p),
12763  *p++ = DUK__SER_STRING;
12764  p = duk__dump_hstring_raw(p, h_str);
12765  } else {
12766  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
12767  p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1 + 8, p);
12768  *p++ = DUK__SER_NUMBER;
12769  d = DUK_TVAL_GET_NUMBER(tv);
12770  DUK_RAW_WRITE_DOUBLE_BE(p, d);
12771  }
12772  tv++;
12773  }
12774 
12775  /* Inner functions recursively. */
12776  fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
12777  fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
12778  while (fn != fn_end) {
12779  /* XXX: This causes recursion up to inner function depth
12780  * which is normally not an issue, e.g. mark-and-sweep uses
12781  * a recursion limiter to avoid C stack issues. Avoiding
12782  * this would mean some sort of a work list or just refusing
12783  * to serialize deep functions.
12784  */
12785  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
12786  p = duk__dump_func(ctx, (duk_hcompfunc *) *fn, bw_ctx, p);
12787  fn++;
12788  }
12789 
12790  /* Lexenv and varenv are not dumped. */
12791 
12792  /* Object extra properties.
12793  *
12794  * There are some difference between function templates and functions.
12795  * For example, function templates don't have .length and nargs is
12796  * normally used to instantiate the functions.
12797  */
12798 
12799  p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
12800 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
12801  p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
12802 #endif
12803 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
12804  p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
12805 #endif
12806 #if defined(DUK_USE_PC2LINE)
12807  p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
12808 #endif
12809  p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
12810  p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
12811 
12812  DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
12813 
12814  return p;
12815 }
12816 
12817 /* Load a function from bytecode. The function object returned here must
12818  * match what is created by duk_js_push_closure() with respect to its flags,
12819  * properties, etc.
12820  *
12821  * NOTE: there are intentionally no input buffer length / bound checks.
12822  * Adding them would be easy but wouldn't ensure memory safety as untrusted
12823  * or broken bytecode is unsafe during execution unless the opcodes themselves
12824  * are validated (which is quite complex, especially for indirect opcodes).
12825  */
12826 
12827 #define DUK__ASSERT_LEFT(n) do { \
12828  DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
12829  } while (0)
12830 
12831 static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t *p_end) {
12832  duk_hthread *thr;
12833  duk_hcompfunc *h_fun;
12834  duk_hbuffer *h_data;
12835  duk_size_t data_size;
12836  duk_uint32_t count_instr, count_const, count_funcs;
12837  duk_uint32_t n;
12838  duk_uint32_t tmp32;
12839  duk_small_uint_t const_type;
12840  duk_uint8_t *fun_data;
12841  duk_uint8_t *q;
12842  duk_idx_t idx_base;
12843  duk_tval *tv1;
12844  duk_uarridx_t arr_idx;
12845  duk_hobject *func_env;
12846  duk_bool_t need_pop;
12847 
12848  /* XXX: There's some overlap with duk_js_closure() here, but
12849  * seems difficult to share code. Ensure that the final function
12850  * looks the same as created by duk_js_closure().
12851  */
12852 
12853  DUK_ASSERT(ctx != NULL);
12854  thr = (duk_hthread *) ctx;
12855 
12856  DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
12857 
12858  DUK__ASSERT_LEFT(3 * 4);
12859  count_instr = DUK_RAW_READ_U32_BE(p);
12860  count_const = DUK_RAW_READ_U32_BE(p);
12861  count_funcs = DUK_RAW_READ_U32_BE(p);
12862 
12863  data_size = sizeof(duk_tval) * count_const +
12864  sizeof(duk_hobject *) * count_funcs +
12865  sizeof(duk_instr_t) * count_instr;
12866 
12867  DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
12868  (long) count_instr, (long) count_const,
12869  (long) count_const, (long) data_size));
12870 
12871  /* Value stack is used to ensure reachability of constants and
12872  * inner functions being loaded. Require enough space to handle
12873  * large functions correctly.
12874  */
12875  duk_require_stack(ctx, 2 + count_const + count_funcs);
12876  idx_base = duk_get_top(ctx);
12877 
12878  /* Push function object, init flags etc. This must match
12879  * duk_js_push_closure() quite carefully.
12880  */
12881  h_fun = duk_push_hcompfunc(ctx);
12882  DUK_ASSERT(h_fun != NULL);
12883  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
12884  DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
12885  DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
12886  DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
12887  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
12888 
12889  h_fun->nregs = DUK_RAW_READ_U16_BE(p);
12890  h_fun->nargs = DUK_RAW_READ_U16_BE(p);
12891 #if defined(DUK_USE_DEBUGGER_SUPPORT)
12892  h_fun->start_line = DUK_RAW_READ_U32_BE(p);
12893  h_fun->end_line = DUK_RAW_READ_U32_BE(p);
12894 #else
12895  p += 8; /* skip line info */
12896 #endif
12897 
12898  /* duk_hcompfunc flags; quite version specific */
12899  tmp32 = DUK_RAW_READ_U32_BE(p);
12900  DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32); /* masks flags to only change duk_hobject flags */
12901 
12902  /* standard prototype */
12903  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
12904 
12905  /* assert just a few critical flags */
12906  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
12907  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
12908  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
12909  DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
12910  DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&h_fun->obj));
12911  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
12912  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
12913  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
12914 
12915  /* Create function 'data' buffer but don't attach it yet. */
12916  fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, data_size);
12917  DUK_ASSERT(fun_data != NULL);
12918 
12919  /* Load bytecode instructions. */
12920  DUK_ASSERT(sizeof(duk_instr_t) == 4);
12921  DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
12922 #if defined(DUK_USE_INTEGER_BE)
12923  q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12924  DUK_MEMCPY((void *) q,
12925  (const void *) p,
12926  sizeof(duk_instr_t) * count_instr);
12927  p += sizeof(duk_instr_t) * count_instr;
12928 #else
12929  q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
12930  for (n = count_instr; n > 0; n--) {
12931  *((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
12932  q += sizeof(duk_instr_t);
12933  }
12934 #endif
12935 
12936  /* Load constants onto value stack but don't yet copy to buffer. */
12937  for (n = count_const; n > 0; n--) {
12938  DUK__ASSERT_LEFT(1);
12939  const_type = DUK_RAW_READ_U8(p);
12940  switch (const_type) {
12941  case DUK__SER_STRING: {
12942  p = duk__load_string_raw(ctx, p);
12943  break;
12944  }
12945  case DUK__SER_NUMBER: {
12946  /* Important to do a fastint check so that constants are
12947  * properly read back as fastints.
12948  */
12949  duk_tval tv_tmp;
12950  duk_double_t val;
12951  DUK__ASSERT_LEFT(8);
12952  val = DUK_RAW_READ_DOUBLE_BE(p);
12953  DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
12954  duk_push_tval(ctx, &tv_tmp);
12955  break;
12956  }
12957  default: {
12958  goto format_error;
12959  }
12960  }
12961  }
12962 
12963  /* Load inner functions to value stack, but don't yet copy to buffer. */
12964  for (n = count_funcs; n > 0; n--) {
12965  p = duk__load_func(ctx, p, p_end);
12966  if (p == NULL) {
12967  goto format_error;
12968  }
12969  }
12970 
12971  /* With constants and inner functions on value stack, we can now
12972  * atomically finish the function 'data' buffer, bump refcounts,
12973  * etc.
12974  *
12975  * Here we take advantage of the value stack being just a duk_tval
12976  * array: we can just memcpy() the constants as long as we incref
12977  * them afterwards.
12978  */
12979 
12980  h_data = (duk_hbuffer *) duk_known_hbuffer(ctx, idx_base + 1);
12981  DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
12982  DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
12983  DUK_HBUFFER_INCREF(thr, h_data);
12984 
12985  tv1 = duk_get_tval(ctx, idx_base + 2); /* may be NULL if no constants or inner funcs */
12986  DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
12987 
12988  q = fun_data;
12989  if (count_const > 0) {
12990  /* Explicit zero size check to avoid NULL 'tv1'. */
12991  DUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
12992  for (n = count_const; n > 0; n--) {
12993  DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q); /* no side effects */
12994  q += sizeof(duk_tval);
12995  }
12996  tv1 += count_const;
12997  }
12998 
12999  DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
13000  for (n = count_funcs; n > 0; n--) {
13001  duk_hobject *h_obj;
13002 
13003  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
13004  h_obj = DUK_TVAL_GET_OBJECT(tv1);
13005  DUK_ASSERT(h_obj != NULL);
13006  tv1++;
13007  DUK_HOBJECT_INCREF(thr, h_obj);
13008 
13009  *((duk_hobject **) (void *) q) = h_obj;
13010  q += sizeof(duk_hobject *);
13011  }
13012 
13013  DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
13014 
13015  /* The function object is now reachable and refcounts are fine,
13016  * so we can pop off all the temporaries.
13017  */
13018  DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(ctx, idx_base)));
13019  duk_set_top(ctx, idx_base + 1);
13020 
13021  /* Setup function properties. */
13022  tmp32 = DUK_RAW_READ_U32_BE(p);
13023  duk_push_u32(ctx, tmp32);
13024  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
13025 
13026 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13027  p = duk__load_string_raw(ctx, p); /* -> [ func funcname ] */
13028  func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
13029  DUK_ASSERT(func_env != NULL);
13030  need_pop = 0;
13031  if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
13032  /* Original function instance/template had NAMEBINDING.
13033  * Must create a lexical environment on loading to allow
13034  * recursive functions like 'function foo() { foo(); }'.
13035  */
13036  duk_hobject *new_env;
13037 
13038  new_env = duk_push_object_helper_proto(ctx,
13039  DUK_HOBJECT_FLAG_EXTENSIBLE |
13040  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
13041  func_env);
13042  DUK_ASSERT(new_env != NULL);
13043  func_env = new_env;
13044 
13045  duk_dup_m2(ctx); /* -> [ func funcname env funcname ] */
13046  duk_dup(ctx, idx_base); /* -> [ func funcname env funcname func ] */
13047  duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ func funcname env ] */
13048 
13049  need_pop = 1; /* Need to pop env, but -after- updating h_fun and increfs. */
13050  }
13051  DUK_ASSERT(func_env != NULL);
13052  DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
13053  DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
13054  DUK_HOBJECT_INCREF(thr, func_env);
13055  DUK_HOBJECT_INCREF(thr, func_env);
13056  if (need_pop) {
13057  duk_pop(ctx);
13058  }
13059  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
13060 #endif /* DUK_USE_FUNC_NAME_PROPERTY */
13061 
13062 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
13063  p = duk__load_string_raw(ctx, p);
13064  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
13065 #endif /* DUK_USE_FUNC_FILENAME_PROPERTY */
13066 
13067  if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
13068  /* Restore empty external .prototype only for constructable
13069  * functions.
13070  */
13071  duk_push_object(ctx);
13072  duk_dup_m2(ctx);
13073  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* func.prototype.constructor = func */
13074  duk_compact_m1(ctx);
13075  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
13076  }
13077 
13078 #if defined(DUK_USE_PC2LINE)
13079  p = duk__load_buffer_raw(ctx, p);
13080  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
13081 #endif /* DUK_USE_PC2LINE */
13082 
13083  duk_push_object(ctx); /* _Varmap */
13084  for (;;) {
13085  /* XXX: awkward */
13086  p = duk__load_string_raw(ctx, p);
13087  if (duk_get_length(ctx, -1) == 0) {
13088  duk_pop(ctx);
13089  break;
13090  }
13091  tmp32 = DUK_RAW_READ_U32_BE(p);
13092  duk_push_u32(ctx, tmp32);
13093  duk_put_prop(ctx, -3);
13094  }
13095  duk_compact_m1(ctx);
13096  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
13097 
13098  /* If _Formals wasn't present in the original function, the list
13099  * here will be empty. Same happens if _Formals was present but
13100  * had zero length. We can omit _Formals from the result if its
13101  * length is zero and matches nargs.
13102  */
13103  duk_push_array(ctx); /* _Formals */
13104  for (arr_idx = 0; ; arr_idx++) {
13105  /* XXX: awkward */
13106  p = duk__load_string_raw(ctx, p);
13107  if (duk_get_length(ctx, -1) == 0) {
13108  duk_pop(ctx);
13109  break;
13110  }
13111  duk_put_prop_index(ctx, -2, arr_idx);
13112  }
13113  if (arr_idx == 0 && h_fun->nargs == 0) {
13114  duk_pop(ctx);
13115  } else {
13116  duk_compact_m1(ctx);
13117  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
13118  }
13119 
13120  /* Return with final function pushed on stack top. */
13121  DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(ctx, -1)));
13122  DUK_ASSERT_TOP(ctx, idx_base + 1);
13123  return p;
13124 
13125  format_error:
13126  return NULL;
13127 }
13128 
13129 DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
13130  duk_hthread *thr;
13131  duk_hcompfunc *func;
13132  duk_bufwriter_ctx bw_ctx_alloc;
13133  duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
13134  duk_uint8_t *p;
13135 
13136  DUK_ASSERT(ctx != NULL);
13137  thr = (duk_hthread *) ctx;
13138 
13139  /* Bound functions don't have all properties so we'd either need to
13140  * lookup the non-bound target function or reject bound functions.
13141  * For now, bound functions are rejected.
13142  */
13143  func = duk_require_hcompfunc(ctx, -1);
13144  DUK_ASSERT(func != NULL);
13145  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
13146 
13147  /* Estimating the result size beforehand would be costly, so
13148  * start with a reasonable size and extend as needed.
13149  */
13150  DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
13151  p = DUK_BW_GET_PTR(thr, bw_ctx);
13152  *p++ = DUK__SER_MARKER;
13153  *p++ = DUK__SER_VERSION;
13154  p = duk__dump_func(ctx, func, bw_ctx, p);
13155  DUK_BW_SET_PTR(thr, bw_ctx, p);
13156  DUK_BW_COMPACT(thr, bw_ctx);
13157 
13158  DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(ctx, -1)));
13159 
13160  duk_remove_m2(ctx); /* [ ... func buf ] -> [ ... buf ] */
13161 }
13162 
13163 DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
13164  duk_hthread *thr;
13165  duk_uint8_t *p_buf, *p, *p_end;
13166  duk_size_t sz;
13167 
13168  DUK_ASSERT(ctx != NULL);
13169  thr = (duk_hthread *) ctx;
13170  DUK_UNREF(ctx);
13171 
13172  p_buf = (duk_uint8_t *) duk_require_buffer(ctx, -1, &sz);
13173  DUK_ASSERT(p_buf != NULL);
13174 
13175  /* The caller is responsible for being sure that bytecode being loaded
13176  * is valid and trusted. Invalid bytecode can cause memory unsafe
13177  * behavior directly during loading or later during bytecode execution
13178  * (instruction validation would be quite complex to implement).
13179  *
13180  * This signature check is the only sanity check for detecting
13181  * accidental invalid inputs. The initial 0xFF byte ensures no
13182  * ordinary string will be accepted by accident.
13183  */
13184  p = p_buf;
13185  p_end = p_buf + sz;
13186  if (sz < 2 || p[0] != DUK__SER_MARKER || p[1] != DUK__SER_VERSION) {
13187  goto format_error;
13188  }
13189  p += 2;
13190 
13191  p = duk__load_func(ctx, p, p_end);
13192  if (p == NULL) {
13193  goto format_error;
13194  }
13195 
13196  duk_remove_m2(ctx); /* [ ... buf func ] -> [ ... func ] */
13197  return;
13198 
13199  format_error:
13200  DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
13201 }
13202 
13203 #else /* DUK_USE_BYTECODE_DUMP_SUPPORT */
13204 
13205 DUK_EXTERNAL void duk_dump_function(duk_context *ctx) {
13206  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
13207 }
13208 
13209 DUK_EXTERNAL void duk_load_function(duk_context *ctx) {
13210  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
13211 }
13212 
13213 #endif /* DUK_USE_BYTECODE_DUMP_SUPPORT */
13214 
13215 /* automatic undefs */
13216 #undef DUK__ASSERT_LEFT
13217 #undef DUK__BYTECODE_INITIAL_ALLOC
13218 #undef DUK__SER_MARKER
13219 #undef DUK__SER_NUMBER
13220 #undef DUK__SER_STRING
13221 #undef DUK__SER_VERSION
13222 /*
13223  * Calls.
13224  *
13225  * Protected variants should avoid ever throwing an error.
13226  */
13227 
13228 /* #include duk_internal.h -> already included */
13229 
13230 /* Prepare value stack for a method call through an object property.
13231  * May currently throw an error e.g. when getting the property.
13232  */
13233 DUK_LOCAL void duk__call_prop_prep_stack(duk_context *ctx, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
13234  DUK_ASSERT_CTX_VALID(ctx);
13235 
13236  DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
13237  (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(ctx)));
13238 
13239  /* [... key arg1 ... argN] */
13240 
13241  /* duplicate key */
13242  duk_dup(ctx, -nargs - 1); /* Note: -nargs alone would fail for nargs == 0, this is OK */
13243  duk_get_prop(ctx, normalized_obj_idx);
13244 
13245  DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
13246 
13247  /* [... key arg1 ... argN func] */
13248 
13249  duk_replace(ctx, -nargs - 2);
13250 
13251  /* [... func arg1 ... argN] */
13252 
13253  duk_dup(ctx, normalized_obj_idx);
13254  duk_insert(ctx, -nargs - 1);
13255 
13256  /* [... func this arg1 ... argN] */
13257 }
13258 
13259 DUK_EXTERNAL void duk_call(duk_context *ctx, duk_idx_t nargs) {
13260  duk_hthread *thr = (duk_hthread *) ctx;
13261  duk_small_uint_t call_flags;
13262  duk_idx_t idx_func;
13263 
13264  DUK_ASSERT_CTX_VALID(ctx);
13265  DUK_ASSERT(thr != NULL);
13266 
13267  idx_func = duk_get_top(ctx) - nargs - 1;
13268  if (idx_func < 0 || nargs < 0) {
13269  /* note that we can't reliably pop anything here */
13270  DUK_ERROR_TYPE_INVALID_ARGS(thr);
13271  }
13272 
13273  /* XXX: awkward; we assume there is space for this, overwrite
13274  * directly instead?
13275  */
13276  duk_push_undefined(ctx);
13277  duk_insert(ctx, idx_func + 1);
13278 
13279  call_flags = 0; /* not protected, respect reclimit, not constructor */
13280 
13281  duk_handle_call_unprotected(thr, /* thread */
13282  nargs, /* num_stack_args */
13283  call_flags); /* call_flags */
13284 }
13285 
13286 DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs) {
13287  duk_hthread *thr = (duk_hthread *) ctx;
13288  duk_small_uint_t call_flags;
13289  duk_idx_t idx_func;
13290 
13291  DUK_ASSERT_CTX_VALID(ctx);
13292  DUK_ASSERT(thr != NULL);
13293 
13294  idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
13295  if (idx_func < 0 || nargs < 0) {
13296  /* note that we can't reliably pop anything here */
13297  DUK_ERROR_TYPE_INVALID_ARGS(thr);
13298  }
13299 
13300  call_flags = 0; /* not protected, respect reclimit, not constructor */
13301 
13302  duk_handle_call_unprotected(thr, /* thread */
13303  nargs, /* num_stack_args */
13304  call_flags); /* call_flags */
13305 }
13306 
13307 DUK_EXTERNAL void duk_call_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs) {
13308  /*
13309  * XXX: if duk_handle_call() took values through indices, this could be
13310  * made much more sensible. However, duk_handle_call() needs to fudge
13311  * the 'this' and 'func' values to handle bound function chains, which
13312  * is now done "in-place", so this is not a trivial change.
13313  */
13314 
13315  DUK_ASSERT_CTX_VALID(ctx);
13316 
13317  obj_idx = duk_require_normalize_index(ctx, obj_idx); /* make absolute */
13318 
13319  duk__call_prop_prep_stack(ctx, obj_idx, nargs);
13320 
13321  duk_call_method(ctx, nargs);
13322 }
13323 
13324 DUK_EXTERNAL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs) {
13325  duk_hthread *thr = (duk_hthread *) ctx;
13326  duk_small_uint_t call_flags;
13327  duk_idx_t idx_func;
13328  duk_int_t rc;
13329 
13330  DUK_ASSERT_CTX_VALID(ctx);
13331  DUK_ASSERT(thr != NULL);
13332 
13333  idx_func = duk_get_top(ctx) - nargs - 1; /* must work for nargs <= 0 */
13334  if (idx_func < 0 || nargs < 0) {
13335  /* We can't reliably pop anything here because the stack input
13336  * shape is incorrect. So we throw an error; if the caller has
13337  * no catch point for this, a fatal error will occur. Another
13338  * alternative would be to just return an error. But then the
13339  * stack would be in an unknown state which might cause some
13340  * very hard to diagnose problems later on. Also note that even
13341  * if we did not throw an error here, the underlying call handler
13342  * might STILL throw an out-of-memory error or some other internal
13343  * fatal error.
13344  */
13345  DUK_ERROR_TYPE_INVALID_ARGS(thr);
13346  return DUK_EXEC_ERROR; /* unreachable */
13347  }
13348 
13349  /* awkward; we assume there is space for this */
13350  duk_push_undefined(ctx);
13351  duk_insert(ctx, idx_func + 1);
13352 
13353  call_flags = 0; /* respect reclimit, not constructor */
13354 
13355  rc = duk_handle_call_protected(thr, /* thread */
13356  nargs, /* num_stack_args */
13357  call_flags); /* call_flags */
13358 
13359  return rc;
13360 }
13361 
13362 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs) {
13363  duk_hthread *thr = (duk_hthread *) ctx;
13364  duk_small_uint_t call_flags;
13365  duk_idx_t idx_func;
13366  duk_int_t rc;
13367 
13368  DUK_ASSERT_CTX_VALID(ctx);
13369  DUK_ASSERT(thr != NULL);
13370 
13371  idx_func = duk_get_top(ctx) - nargs - 2; /* must work for nargs <= 0 */
13372  if (idx_func < 0 || nargs < 0) {
13373  /* See comments in duk_pcall(). */
13374  DUK_ERROR_TYPE_INVALID_ARGS(thr);
13375  return DUK_EXEC_ERROR; /* unreachable */
13376  }
13377 
13378  call_flags = 0; /* respect reclimit, not constructor */
13379 
13380  rc = duk_handle_call_protected(thr, /* thread */
13381  nargs, /* num_stack_args */
13382  call_flags); /* call_flags */
13383 
13384  return rc;
13385 }
13386 
13388  duk_idx_t obj_idx;
13389  duk_idx_t nargs;
13390 };
13392 
13393 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_context *ctx, void *udata) {
13394  duk_idx_t obj_idx;
13395  duk_idx_t nargs;
13396  duk__pcall_prop_args *args;
13397 
13398  DUK_ASSERT_CTX_VALID(ctx);
13399  DUK_ASSERT(udata != NULL);
13400 
13401  args = (duk__pcall_prop_args *) udata;
13402  obj_idx = args->obj_idx;
13403  nargs = args->nargs;
13404 
13405  obj_idx = duk_require_normalize_index(ctx, obj_idx); /* make absolute */
13406  duk__call_prop_prep_stack(ctx, obj_idx, nargs);
13407  duk_call_method(ctx, nargs);
13408  return 1;
13409 }
13410 
13411 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs) {
13412  duk__pcall_prop_args args;
13413 
13414  /*
13415  * Must be careful to catch errors related to value stack manipulation
13416  * and property lookup, not just the call itself.
13417  */
13418 
13419  DUK_ASSERT_CTX_VALID(ctx);
13420 
13421  args.obj_idx = obj_idx;
13422  args.nargs = nargs;
13423 
13424  /* Inputs: explicit arguments (nargs), +1 for key. If the value stack
13425  * does not contain enough args, an error is thrown; this matches
13426  * behavior of the other protected call API functions.
13427  */
13428  return duk_safe_call(ctx, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
13429 }
13430 
13431 DUK_EXTERNAL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets) {
13432  duk_hthread *thr = (duk_hthread *) ctx;
13433  duk_int_t rc;
13434 
13435  DUK_ASSERT_CTX_VALID(ctx);
13436  DUK_ASSERT(thr != NULL);
13437 
13438  if (duk_get_top(ctx) < nargs || nrets < 0) {
13439  /* See comments in duk_pcall(). */
13440  DUK_ERROR_TYPE_INVALID_ARGS(thr);
13441  return DUK_EXEC_ERROR; /* unreachable */
13442  }
13443 
13444  rc = duk_handle_safe_call(thr, /* thread */
13445  func, /* func */
13446  udata, /* udata */
13447  nargs, /* num_stack_args */
13448  nrets); /* num_stack_res */
13449 
13450  return rc;
13451 }
13452 
13453 DUK_EXTERNAL void duk_new(duk_context *ctx, duk_idx_t nargs) {
13454  /*
13455  * There are two [[Construct]] operations in the specification:
13456  *
13457  * - E5 Section 13.2.2: for Function objects
13458  * - E5 Section 15.3.4.5.2: for "bound" Function objects
13459  *
13460  * The chain of bound functions is resolved in Section 15.3.4.5.2,
13461  * with arguments "piling up" until the [[Construct]] internal
13462  * method is called on the final, actual Function object. Note
13463  * that the "prototype" property is looked up *only* from the
13464  * final object, *before* calling the constructor.
13465  *
13466  * Currently we follow the bound function chain here to get the
13467  * "prototype" property value from the final, non-bound function.
13468  * However, we let duk_handle_call() handle the argument "piling"
13469  * when the constructor is called. The bound function chain is
13470  * thus now processed twice.
13471  *
13472  * When constructing new Array instances, an unnecessary object is
13473  * created and discarded now: the standard [[Construct]] creates an
13474  * object, and calls the Array constructor. The Array constructor
13475  * returns an Array instance, which is used as the result value for
13476  * the "new" operation; the object created before the Array constructor
13477  * call is discarded.
13478  *
13479  * This would be easy to fix, e.g. by knowing that the Array constructor
13480  * will always create a replacement object and skip creating the fallback
13481  * object in that case.
13482  *
13483  * Note: functions called via "new" need to know they are called as a
13484  * constructor. For instance, built-in constructors behave differently
13485  * depending on how they are called.
13486  */
13487 
13488  /* XXX: merge this with duk_js_call.c, as this function implements
13489  * core semantics (or perhaps merge the two files altogether).
13490  */
13491 
13492  duk_hthread *thr = (duk_hthread *) ctx;
13493  duk_hobject *proto;
13494  duk_hobject *cons;
13495  duk_hobject *fallback;
13496  duk_idx_t idx_cons;
13497  duk_small_uint_t call_flags;
13498 
13499  DUK_ASSERT_CTX_VALID(ctx);
13500 
13501  /* [... constructor arg1 ... argN] */
13502 
13503  idx_cons = duk_require_normalize_index(ctx, -nargs - 1);
13504 
13505  DUK_DDD(DUK_DDDPRINT("top=%ld, nargs=%ld, idx_cons=%ld",
13506  (long) duk_get_top(ctx), (long) nargs, (long) idx_cons));
13507 
13508  /* XXX: code duplication */
13509 
13510  /*
13511  * Figure out the final, non-bound constructor, to get "prototype"
13512  * property.
13513  */
13514 
13515  duk_dup(ctx, idx_cons);
13516  for (;;) {
13517  duk_tval *tv;
13518  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
13519  DUK_ASSERT(tv != NULL);
13520 
13521  if (DUK_TVAL_IS_OBJECT(tv)) {
13522  cons = DUK_TVAL_GET_OBJECT(tv);
13523  DUK_ASSERT(cons != NULL);
13524  if (!DUK_HOBJECT_IS_CALLABLE(cons) || !DUK_HOBJECT_HAS_CONSTRUCTABLE(cons)) {
13525  /* Checking callability of the immediate target
13526  * is important, same for constructability.
13527  * Checking it for functions down the bound
13528  * function chain is not strictly necessary
13529  * because .bind() should normally reject them.
13530  * But it's good to check anyway because it's
13531  * technically possible to edit the bound function
13532  * chain via internal keys.
13533  */
13534  goto not_constructable;
13535  }
13536  if (!DUK_HOBJECT_HAS_BOUNDFUNC(cons)) {
13537  break;
13538  }
13539  } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
13540  /* Lightfuncs cannot be bound. */
13541  break;
13542  } else {
13543  /* Anything else is not constructable. */
13544  goto not_constructable;
13545  }
13546  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [... cons target] */
13547  duk_remove_m2(ctx); /* -> [... target] */
13548  }
13549  DUK_ASSERT(duk_is_callable(ctx, -1));
13550  DUK_ASSERT(duk_is_lightfunc(ctx, -1) ||
13551  (duk_get_hobject(ctx, -1) != NULL && !DUK_HOBJECT_HAS_BOUNDFUNC(duk_get_hobject(ctx, -1))));
13552 
13553  /* [... constructor arg1 ... argN final_cons] */
13554 
13555  /*
13556  * Create "fallback" object to be used as the object instance,
13557  * unless the constructor returns a replacement value.
13558  * Its internal prototype needs to be set based on "prototype"
13559  * property of the constructor.
13560  */
13561 
13562  duk_push_object(ctx); /* class Object, extensible */
13563 
13564  /* [... constructor arg1 ... argN final_cons fallback] */
13565 
13566  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_PROTOTYPE);
13567  proto = duk_get_hobject(ctx, -1);
13568  if (!proto) {
13569  DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
13570  "-> leave standard Object prototype as fallback prototype"));
13571  } else {
13572  DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
13573  "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
13574  fallback = duk_get_hobject(ctx, -2);
13575  DUK_ASSERT(fallback != NULL);
13576  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
13577  }
13578  duk_pop(ctx);
13579 
13580  /* [... constructor arg1 ... argN final_cons fallback] */
13581 
13582  /*
13583  * Manipulate callstack for the call.
13584  */
13585 
13586  duk_dup_top(ctx);
13587  duk_insert(ctx, idx_cons + 1); /* use fallback as 'this' value */
13588  duk_insert(ctx, idx_cons); /* also stash it before constructor,
13589  * in case we need it (as the fallback value)
13590  */
13591  duk_pop(ctx); /* pop final_cons */
13592 
13593 
13594  /* [... fallback constructor fallback(this) arg1 ... argN];
13595  * Note: idx_cons points to first 'fallback', not 'constructor'.
13596  */
13597 
13598  DUK_DDD(DUK_DDDPRINT("before call, idx_cons+1 (constructor) -> %!T, idx_cons+2 (fallback/this) -> %!T, "
13599  "nargs=%ld, top=%ld",
13600  (duk_tval *) duk_get_tval(ctx, idx_cons + 1),
13601  (duk_tval *) duk_get_tval(ctx, idx_cons + 2),
13602  (long) nargs,
13603  (long) duk_get_top(ctx)));
13604 
13605  /*
13606  * Call the constructor function (called in "constructor mode").
13607  */
13608 
13609  call_flags = DUK_CALL_FLAG_CONSTRUCTOR_CALL; /* not protected, respect reclimit, is a constructor call */
13610 
13611  duk_handle_call_unprotected(thr, /* thread */
13612  nargs, /* num_stack_args */
13613  call_flags); /* call_flags */
13614 
13615  /* [... fallback retval] */
13616 
13617  DUK_DDD(DUK_DDDPRINT("constructor call finished, fallback=%!iT, retval=%!iT",
13618  (duk_tval *) duk_get_tval(ctx, -2),
13619  (duk_tval *) duk_get_tval(ctx, -1)));
13620 
13621  /*
13622  * Determine whether to use the constructor return value as the created
13623  * object instance or not.
13624  */
13625 
13626  if (duk_check_type_mask(ctx, -1, DUK_TYPE_MASK_OBJECT |
13627  DUK_TYPE_MASK_BUFFER |
13628  DUK_TYPE_MASK_LIGHTFUNC)) {
13629  duk_remove_m2(ctx);
13630  } else {
13631  duk_pop(ctx);
13632  }
13633 
13634  /*
13635  * Augment created errors upon creation (not when they are thrown or
13636  * rethrown). __FILE__ and __LINE__ are not desirable here; the call
13637  * stack reflects the caller which is correct.
13638  */
13639 
13640 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
13641  duk_hthread_sync_currpc(thr);
13642  duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
13643 #endif
13644 
13645  /* [... retval] */
13646 
13647  return;
13648 
13649  not_constructable:
13650 #if defined(DUK_USE_VERBOSE_ERRORS)
13651 #if defined(DUK_USE_PARANOID_ERRORS)
13652  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(ctx, -1));
13653 #else
13654  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_readable(ctx, -1));
13655 #endif
13656 #else
13657  DUK_ERROR_TYPE(thr, "not constructable");
13658 #endif
13659 }
13660 
13661 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_context *ctx, void *udata) {
13662  duk_idx_t nargs;
13663 
13664  DUK_ASSERT(udata != NULL);
13665  nargs = *((duk_idx_t *) udata);
13666 
13667  duk_new(ctx, nargs);
13668  return 1;
13669 }
13670 
13671 DUK_EXTERNAL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs) {
13672  duk_int_t rc;
13673 
13674  DUK_ASSERT_CTX_VALID(ctx);
13675 
13676  /* For now, just use duk_safe_call() to wrap duk_new(). We can't
13677  * simply use a protected duk_handle_call() because there's post
13678  * processing which might throw. It should be possible to ensure
13679  * the post processing never throws (except in internal errors and
13680  * out of memory etc which are always allowed) and then remove this
13681  * wrapper.
13682  */
13683 
13684  rc = duk_safe_call(ctx, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
13685  return rc;
13686 }
13687 
13688 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
13689  duk_hthread *thr = (duk_hthread *) ctx;
13690  duk_activation *act;
13691 
13692  DUK_ASSERT_CTX_VALID(ctx);
13693  DUK_ASSERT(thr != NULL);
13694  DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
13695 
13696  act = duk_hthread_get_current_activation(thr);
13697  DUK_ASSERT(act != NULL); /* because callstack_top > 0 */
13698  return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
13699 }
13700 
13701 /* XXX: Make this obsolete by adding a function flag for rejecting a
13702  * non-constructor call automatically?
13703  */
13704 DUK_INTERNAL void duk_require_constructor_call(duk_context *ctx) {
13705  if (!duk_is_constructor_call(ctx)) {
13706  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CONSTRUCT_ONLY);
13707  }
13708 }
13709 
13710 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_context *ctx) {
13711  duk_hthread *thr = (duk_hthread *) ctx;
13712  duk_activation *act;
13713 
13714  /* For user code this could just return 1 (strict) always
13715  * because all Duktape/C functions are considered strict,
13716  * and strict is also the default when nothing is running.
13717  * However, Duktape may call this function internally when
13718  * the current activation is an Ecmascript function, so
13719  * this cannot be replaced by a 'return 1' without fixing
13720  * the internal call sites.
13721  */
13722 
13723  DUK_ASSERT_CTX_VALID(ctx);
13724  DUK_ASSERT(thr != NULL);
13725  DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
13726 
13727  act = duk_hthread_get_current_activation(thr);
13728  if (act == NULL) {
13729  /* Strict by default. */
13730  return 1;
13731  }
13732  return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
13733 }
13734 
13735 /*
13736  * Duktape/C function magic
13737  */
13738 
13739 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_context *ctx) {
13740  duk_hthread *thr = (duk_hthread *) ctx;
13741  duk_activation *act;
13742  duk_hobject *func;
13743 
13744  DUK_ASSERT_CTX_VALID(ctx);
13745  DUK_ASSERT(thr != NULL);
13746  DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
13747 
13748  act = duk_hthread_get_current_activation(thr);
13749  if (act) {
13750  func = DUK_ACT_GET_FUNC(act);
13751  if (!func) {
13752  duk_tval *tv = &act->tv_func;
13753  duk_small_uint_t lf_flags;
13754  lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
13755  return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
13756  }
13757  DUK_ASSERT(func != NULL);
13758 
13759  if (DUK_HOBJECT_IS_NATFUNC(func)) {
13760  duk_hnatfunc *nf = (duk_hnatfunc *) func;
13761  return (duk_int_t) nf->magic;
13762  }
13763  }
13764  return 0;
13765 }
13766 
13767 DUK_EXTERNAL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t idx) {
13768  duk_hthread *thr = (duk_hthread *) ctx;
13769  duk_tval *tv;
13770  duk_hobject *h;
13771 
13772  DUK_ASSERT_CTX_VALID(ctx);
13773 
13774  tv = duk_require_tval(ctx, idx);
13775  if (DUK_TVAL_IS_OBJECT(tv)) {
13776  h = DUK_TVAL_GET_OBJECT(tv);
13777  DUK_ASSERT(h != NULL);
13778  if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
13779  goto type_error;
13780  }
13781  return (duk_int_t) ((duk_hnatfunc *) h)->magic;
13782  } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
13783  duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
13784  return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
13785  }
13786 
13787  /* fall through */
13788  type_error:
13789  DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
13790  return 0;
13791 }
13792 
13793 DUK_EXTERNAL void duk_set_magic(duk_context *ctx, duk_idx_t idx, duk_int_t magic) {
13794  duk_hnatfunc *nf;
13795 
13796  DUK_ASSERT_CTX_VALID(ctx);
13797 
13798  nf = duk_require_hnatfunc(ctx, idx);
13799  DUK_ASSERT(nf != NULL);
13800  nf->magic = (duk_int16_t) magic;
13801 }
13802 
13803 /*
13804  * Misc helpers
13805  */
13806 
13807 DUK_INTERNAL void duk_resolve_nonbound_function(duk_context *ctx) {
13808  duk_uint_t sanity;
13809  duk_tval *tv;
13810 
13811  sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
13812  do {
13813  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
13814  if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
13815  /* Lightweight function: never bound, so terminate. */
13816  break;
13817  } else if (DUK_TVAL_IS_OBJECT(tv)) {
13818  duk_hobject *func;
13819 
13820  func = DUK_TVAL_GET_OBJECT(tv);
13821  DUK_ASSERT(func != NULL);
13822  if (!DUK_HOBJECT_IS_CALLABLE(func) || !DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
13823  break;
13824  }
13825  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_TARGET);
13826  duk_replace(ctx, -2);
13827  } else {
13828  break;
13829  }
13830  } while (--sanity > 0);
13831 }
13832 /*
13833  * Encoding and decoding basic formats: hex, base64.
13834  *
13835  * These are in-place operations which may allow an optimized implementation.
13836  *
13837  * Base-64: https://tools.ietf.org/html/rfc4648#section-4
13838  */
13839 
13840 /* #include duk_internal.h -> already included */
13841 
13842 /* Shared handling for encode/decode argument. Fast path handling for
13843  * buffer and string values because they're the most common. In particular,
13844  * avoid creating a temporary string or buffer when possible.
13845  */
13846 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
13847  void *ptr;
13848  duk_bool_t isbuffer;
13849 
13850  DUK_ASSERT(duk_is_valid_index(ctx, idx)); /* checked by caller */
13851 
13852  ptr = duk_get_buffer_data_raw(ctx, idx, out_len, 0 /*throw_flag*/, &isbuffer);
13853  if (isbuffer) {
13854  DUK_ASSERT(*out_len == 0 || ptr != NULL);
13855  return (const duk_uint8_t *) ptr;
13856  }
13857  return (const duk_uint8_t *) duk_to_lstring(ctx, idx, out_len);
13858 }
13859 
13860 #if defined(DUK_USE_BASE64_FASTPATH)
13861 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
13862  duk_uint_t t;
13863  duk_size_t n_full, n_full3, n_final;
13864  const duk_uint8_t *src_end_fast;
13865 
13866  n_full = srclen / 3; /* full 3-byte -> 4-char conversions */
13867  n_full3 = n_full * 3;
13868  n_final = srclen - n_full3;
13869  DUK_ASSERT_DISABLE(n_final >= 0);
13870  DUK_ASSERT(n_final <= 2);
13871 
13872  src_end_fast = src + n_full3;
13873  while (DUK_UNLIKELY(src != src_end_fast)) {
13874  t = (duk_uint_t) (*src++);
13875  t = (t << 8) + (duk_uint_t) (*src++);
13876  t = (t << 8) + (duk_uint_t) (*src++);
13877 
13878  *dst++ = duk_base64_enctab[t >> 18];
13879  *dst++ = duk_base64_enctab[(t >> 12) & 0x3f];
13880  *dst++ = duk_base64_enctab[(t >> 6) & 0x3f];
13881  *dst++ = duk_base64_enctab[t & 0x3f];
13882 
13883 #if 0 /* Tested: not faster on x64 */
13884  /* aaaaaabb bbbbcccc ccdddddd */
13885  dst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];
13886  dst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];
13887  dst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];
13888  dst[3] = duk_base64_enctab[src[2] & 0x3f];
13889  src += 3; dst += 4;
13890 #endif
13891  }
13892 
13893  switch (n_final) {
13894  /* case 0: nop */
13895  case 1: {
13896  /* XX== */
13897  t = (duk_uint_t) (*src++);
13898  *dst++ = duk_base64_enctab[t >> 2]; /* XXXXXX-- */
13899  *dst++ = duk_base64_enctab[(t << 4) & 0x3f]; /* ------XX */
13900  *dst++ = DUK_ASC_EQUALS;
13901  *dst++ = DUK_ASC_EQUALS;
13902  break;
13903  }
13904  case 2: {
13905  /* XXX= */
13906  t = (duk_uint_t) (*src++);
13907  t = (t << 8) + (duk_uint_t) (*src++);
13908  *dst++ = duk_base64_enctab[t >> 10]; /* XXXXXX-- -------- */
13909  *dst++ = duk_base64_enctab[(t >> 4) & 0x3f]; /* ------XX XXXX---- */
13910  *dst++ = duk_base64_enctab[(t << 2) & 0x3f]; /* -------- ----XXXX */
13911  *dst++ = DUK_ASC_EQUALS;
13912  break;
13913  }
13914  }
13915 }
13916 #else /* DUK_USE_BASE64_FASTPATH */
13917 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
13918  duk_small_uint_t i, snip;
13919  duk_uint_t t;
13920  duk_uint_fast8_t x, y;
13921  const duk_uint8_t *src_end;
13922 
13923  src_end = src + srclen;
13924 
13925  while (src < src_end) {
13926  /* read 3 bytes into 't', padded by zero */
13927  snip = 4;
13928  t = 0;
13929  for (i = 0; i < 3; i++) {
13930  t = t << 8;
13931  if (src >= src_end) {
13932  snip--;
13933  } else {
13934  t += (duk_uint_t) (*src++);
13935  }
13936  }
13937 
13938  /*
13939  * Missing bytes snip base64 example
13940  * 0 4 XXXX
13941  * 1 3 XXX=
13942  * 2 2 XX==
13943  */
13944 
13945  DUK_ASSERT(snip >= 2 && snip <= 4);
13946 
13947  for (i = 0; i < 4; i++) {
13948  x = (duk_uint_fast8_t) ((t >> 18) & 0x3f);
13949  t = t << 6;
13950 
13951  /* A straightforward 64-byte lookup would be faster
13952  * and cleaner, but this is shorter.
13953  */
13954  if (i >= snip) {
13955  y = '=';
13956  } else if (x <= 25) {
13957  y = x + 'A';
13958  } else if (x <= 51) {
13959  y = x - 26 + 'a';
13960  } else if (x <= 61) {
13961  y = x - 52 + '0';
13962  } else if (x == 62) {
13963  y = '+';
13964  } else {
13965  y = '/';
13966  }
13967 
13968  *dst++ = (duk_uint8_t) y;
13969  }
13970  }
13971 }
13972 #endif /* DUK_USE_BASE64_FASTPATH */
13973 
13974 #if defined(DUK_USE_BASE64_FASTPATH)
13975 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) {
13976  duk_int_t x;
13977  duk_int_t t;
13978  duk_small_uint_t n_equal;
13979  duk_small_uint_t n_chars;
13980  const duk_uint8_t *src_end;
13981  const duk_uint8_t *src_end_safe;
13982 
13983  src_end = src + srclen;
13984  src_end_safe = src_end - 4; /* if 'src < src_end_safe', safe to read 4 bytes */
13985 
13986  /* Innermost fast path processes 4 valid base-64 characters at a time
13987  * but bails out on whitespace, padding chars ('=') and invalid chars.
13988  * Once the slow path segment has been processed, we return to the
13989  * inner fast path again. This handles e.g. base64 with newlines
13990  * reasonably well because the majority of a line is in the fast path.
13991  */
13992  for (;;) {
13993  /* Fast path, handle units with just actual encoding characters. */
13994 
13995  while (src <= src_end_safe) {
13996  /* The lookup byte is intentionally sign extended to (at least)
13997  * 32 bits and then ORed. This ensures that is at least 1 byte
13998  * is negative, the highest bit of 't' will be set at the end
13999  * and we don't need to check every byte.
14000  */
14001  DUK_DDD(DUK_DDDPRINT("fast loop: src=%p, src_end_safe=%p, src_end=%p",
14002  (const void *) src, (const void *) src_end_safe, (const void *) src_end));
14003 
14004  t = (duk_int_t) duk_base64_dectab[*src++];
14005  t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
14006  t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
14007  t = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];
14008 
14009  if (DUK_UNLIKELY(t < 0)) {
14010  DUK_DDD(DUK_DDDPRINT("fast loop unit was not clean, process one slow path unit"));
14011  src -= 4;
14012  break;
14013  }
14014 
14015  DUK_ASSERT(t <= 0xffffffL);
14016  DUK_ASSERT((t >> 24) == 0);
14017  *dst++ = (duk_uint8_t) (t >> 16);
14018  *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
14019  *dst++ = (duk_uint8_t) (t & 0xff);
14020  }
14021 
14022  /* Handle one slow path unit (or finish if we're done). */
14023 
14024  n_equal = 0;
14025  n_chars = 0;
14026  t = 0;
14027  for (;;) {
14028  DUK_DDD(DUK_DDDPRINT("slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld",
14029  (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));
14030 
14031  if (DUK_UNLIKELY(src >= src_end)) {
14032  goto done; /* two level break */
14033  }
14034 
14035  x = duk_base64_dectab[*src++];
14036  if (DUK_UNLIKELY(x < 0)) {
14037  if (x == -2) {
14038  continue; /* allowed ascii whitespace */
14039  } else if (x == -3) {
14040  n_equal++;
14041  t <<= 6;
14042  } else {
14043  DUK_ASSERT(x == -1);
14044  goto error;
14045  }
14046  } else {
14047  DUK_ASSERT(x >= 0 && x <= 63);
14048  if (n_equal > 0) {
14049  /* Don't allow actual chars after equal sign. */
14050  goto error;
14051  }
14052  t = (t << 6) + x;
14053  }
14054 
14055  if (DUK_UNLIKELY(n_chars == 3)) {
14056  /* Emit 3 bytes and backtrack if there was padding. There's
14057  * always space for the whole 3 bytes so no check needed.
14058  */
14059  DUK_ASSERT(t <= 0xffffffL);
14060  DUK_ASSERT((t >> 24) == 0);
14061  *dst++ = (duk_uint8_t) (t >> 16);
14062  *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
14063  *dst++ = (duk_uint8_t) (t & 0xff);
14064 
14065  if (DUK_UNLIKELY(n_equal > 0)) {
14066  DUK_ASSERT(n_equal <= 4);
14067 
14068  /* There may be whitespace between the equal signs. */
14069  if (n_equal == 1) {
14070  /* XXX= */
14071  dst -= 1;
14072  } else if (n_equal == 2) {
14073  /* XX== */
14074  dst -= 2;
14075  } else {
14076  goto error; /* invalid padding */
14077  }
14078 
14079  /* Continue parsing after padding, allows concatenated,
14080  * padded base64.
14081  */
14082  }
14083  break; /* back to fast loop */
14084  } else {
14085  n_chars++;
14086  }
14087  }
14088  }
14089  done:
14090  DUK_DDD(DUK_DDDPRINT("done; src=%p, src_end=%p, n_chars=%ld",
14091  (const void *) src, (const void *) src_end, (long) n_chars));
14092 
14093  DUK_ASSERT(src == src_end);
14094 
14095  if (n_chars != 0) {
14096  /* Here we'd have the option of decoding unpadded base64
14097  * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
14098  * accepted.
14099  */
14100  goto error;
14101  }
14102 
14103  *out_dst_final = dst;
14104  return 1;
14105 
14106  error:
14107  return 0;
14108 }
14109 #else /* DUK_USE_BASE64_FASTPATH */
14110 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) {
14111  duk_uint_t t;
14112  duk_uint_fast8_t x, y;
14113  duk_small_uint_t group_idx;
14114  duk_small_uint_t n_equal;
14115  const duk_uint8_t *src_end;
14116 
14117  src_end = src + srclen;
14118  t = 0;
14119  group_idx = 0;
14120  n_equal = 0;
14121 
14122  while (src < src_end) {
14123  x = *src++;
14124 
14125  if (x >= 'A' && x <= 'Z') {
14126  y = x - 'A' + 0;
14127  } else if (x >= 'a' && x <= 'z') {
14128  y = x - 'a' + 26;
14129  } else if (x >= '0' && x <= '9') {
14130  y = x - '0' + 52;
14131  } else if (x == '+') {
14132  y = 62;
14133  } else if (x == '/') {
14134  y = 63;
14135  } else if (x == '=') {
14136  /* We don't check the zero padding bytes here right now
14137  * (that they're actually zero). This seems to be common
14138  * behavior for base-64 decoders.
14139  */
14140 
14141  n_equal++;
14142  t <<= 6; /* shift in zeroes */
14143  goto skip_add;
14144  } else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {
14145  /* allow basic ASCII whitespace */
14146  continue;
14147  } else {
14148  goto error;
14149  }
14150 
14151  if (n_equal > 0) {
14152  /* Don't allow mixed padding and actual chars. */
14153  goto error;
14154  }
14155  t = (t << 6) + y;
14156  skip_add:
14157 
14158  if (group_idx == 3) {
14159  /* output 3 bytes from 't' */
14160  *dst++ = (duk_uint8_t) ((t >> 16) & 0xff);
14161  *dst++ = (duk_uint8_t) ((t >> 8) & 0xff);
14162  *dst++ = (duk_uint8_t) (t & 0xff);
14163 
14164  if (DUK_UNLIKELY(n_equal > 0)) {
14165  /* Backtrack. */
14166  DUK_ASSERT(n_equal <= 4);
14167  if (n_equal == 1) {
14168  dst -= 1;
14169  } else if (n_equal == 2) {
14170  dst -= 2;
14171  } else {
14172  goto error; /* invalid padding */
14173  }
14174 
14175  /* Here we can choose either to end parsing and ignore
14176  * whatever follows, or to continue parsing in case
14177  * multiple (possibly padded) base64 strings have been
14178  * concatenated. Currently, keep on parsing.
14179  */
14180  n_equal = 0;
14181  }
14182 
14183  t = 0;
14184  group_idx = 0;
14185  } else {
14186  group_idx++;
14187  }
14188  }
14189 
14190  if (group_idx != 0) {
14191  /* Here we'd have the option of decoding unpadded base64
14192  * (e.g. "xxxxyy" instead of "xxxxyy==". Currently not
14193  * accepted.
14194  */
14195  goto error;
14196  }
14197 
14198  *out_dst_final = dst;
14199  return 1;
14200 
14201  error:
14202  return 0;
14203 }
14204 #endif /* DUK_USE_BASE64_FASTPATH */
14205 
14206 DUK_EXTERNAL const char *duk_base64_encode(duk_context *ctx, duk_idx_t idx) {
14207  duk_hthread *thr = (duk_hthread *) ctx;
14208  const duk_uint8_t *src;
14209  duk_size_t srclen;
14210  duk_size_t dstlen;
14211  duk_uint8_t *dst;
14212  const char *ret;
14213 
14214  DUK_ASSERT_CTX_VALID(ctx);
14215 
14216  /* XXX: optimize for string inputs: no need to coerce to a buffer
14217  * which makes a copy of the input.
14218  */
14219 
14220  idx = duk_require_normalize_index(ctx, idx);
14221  src = duk__prep_codec_arg(ctx, idx, &srclen);
14222  /* Note: for srclen=0, src may be NULL */
14223 
14224  /* Computation must not wrap; this limit works for 32-bit size_t:
14225  * >>> srclen = 3221225469
14226  * >>> '%x' % ((srclen + 2) / 3 * 4)
14227  * 'fffffffc'
14228  */
14229  if (srclen > 3221225469UL) {
14230  goto type_error;
14231  }
14232  dstlen = (srclen + 2) / 3 * 4;
14233  dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, dstlen);
14234 
14235  duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
14236 
14237  ret = duk_buffer_to_string(ctx, -1); /* Safe, result is ASCII. */
14238  duk_replace(ctx, idx);
14239  return ret;
14240 
14241  type_error:
14242  DUK_ERROR_TYPE(thr, DUK_STR_ENCODE_FAILED);
14243  return NULL; /* never here */
14244 }
14245 
14246 DUK_EXTERNAL void duk_base64_decode(duk_context *ctx, duk_idx_t idx) {
14247  duk_hthread *thr = (duk_hthread *) ctx;
14248  const duk_uint8_t *src;
14249  duk_size_t srclen;
14250  duk_size_t dstlen;
14251  duk_uint8_t *dst;
14252  duk_uint8_t *dst_final;
14253  duk_bool_t retval;
14254 
14255  DUK_ASSERT_CTX_VALID(ctx);
14256 
14257  /* XXX: optimize for buffer inputs: no need to coerce to a string
14258  * which causes an unnecessary interning.
14259  */
14260 
14261  idx = duk_require_normalize_index(ctx, idx);
14262  src = duk__prep_codec_arg(ctx, idx, &srclen);
14263 
14264  /* Computation must not wrap, only srclen + 3 is at risk of
14265  * wrapping because after that the number gets smaller.
14266  * This limit works for 32-bit size_t:
14267  * 0x100000000 - 3 - 1 = 4294967292
14268  */
14269  if (srclen > 4294967292UL) {
14270  goto type_error;
14271  }
14272  dstlen = (srclen + 3) / 4 * 3; /* upper limit, assuming no whitespace etc */
14273  dst = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, dstlen);
14274  /* Note: for dstlen=0, dst may be NULL */
14275 
14276  retval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);
14277  if (!retval) {
14278  goto type_error;
14279  }
14280 
14281  /* XXX: convert to fixed buffer? */
14282  (void) duk_resize_buffer(ctx, -1, (duk_size_t) (dst_final - dst));
14283  duk_replace(ctx, idx);
14284  return;
14285 
14286  type_error:
14287  DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
14288 }
14289 
14290 DUK_EXTERNAL const char *duk_hex_encode(duk_context *ctx, duk_idx_t idx) {
14291  const duk_uint8_t *inp;
14292  duk_size_t len;
14293  duk_size_t i;
14294  duk_uint8_t *buf;
14295  const char *ret;
14296 #if defined(DUK_USE_HEX_FASTPATH)
14297  duk_size_t len_safe;
14298  duk_uint16_t *p16;
14299 #endif
14300 
14301  DUK_ASSERT_CTX_VALID(ctx);
14302 
14303  idx = duk_require_normalize_index(ctx, idx);
14304  inp = duk__prep_codec_arg(ctx, idx, &len);
14305  DUK_ASSERT(inp != NULL || len == 0);
14306 
14307  /* Fixed buffer, no zeroing because we'll fill all the data. */
14308  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, len * 2);
14309  DUK_ASSERT(buf != NULL);
14310 
14311 #if defined(DUK_USE_HEX_FASTPATH)
14312  DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0); /* pointer is aligned, guaranteed for fixed buffer */
14313  p16 = (duk_uint16_t *) (void *) buf;
14314  len_safe = len & ~0x03U;
14315  for (i = 0; i < len_safe; i += 4) {
14316  p16[0] = duk_hex_enctab[inp[i]];
14317  p16[1] = duk_hex_enctab[inp[i + 1]];
14318  p16[2] = duk_hex_enctab[inp[i + 2]];
14319  p16[3] = duk_hex_enctab[inp[i + 3]];
14320  p16 += 4;
14321  }
14322  for (; i < len; i++) {
14323  *p16++ = duk_hex_enctab[inp[i]];
14324  }
14325 #else /* DUK_USE_HEX_FASTPATH */
14326  for (i = 0; i < len; i++) {
14327  duk_small_uint_t t;
14328  t = (duk_small_uint_t) inp[i];
14329  buf[i*2 + 0] = duk_lc_digits[t >> 4];
14330  buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
14331  }
14332 #endif /* DUK_USE_HEX_FASTPATH */
14333 
14334  /* XXX: Using a string return value forces a string intern which is
14335  * not always necessary. As a rough performance measure, hex encode
14336  * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
14337  * without string coercion. Change to returning a buffer and let the
14338  * caller coerce to string if necessary?
14339  */
14340 
14341  ret = duk_buffer_to_string(ctx, -1); /* Safe, result is ASCII. */
14342  duk_replace(ctx, idx);
14343  return ret;
14344 }
14345 
14346 DUK_EXTERNAL void duk_hex_decode(duk_context *ctx, duk_idx_t idx) {
14347  duk_hthread *thr = (duk_hthread *) ctx;
14348  const duk_uint8_t *inp;
14349  duk_size_t len;
14350  duk_size_t i;
14351  duk_int_t t;
14352  duk_uint8_t *buf;
14353 #if defined(DUK_USE_HEX_FASTPATH)
14354  duk_int_t chk;
14355  duk_uint8_t *p;
14356  duk_size_t len_safe;
14357 #endif
14358 
14359  DUK_ASSERT_CTX_VALID(ctx);
14360 
14361  idx = duk_require_normalize_index(ctx, idx);
14362  inp = duk__prep_codec_arg(ctx, idx, &len);
14363  DUK_ASSERT(inp != NULL || len == 0);
14364 
14365  if (len & 0x01) {
14366  goto type_error;
14367  }
14368 
14369  /* Fixed buffer, no zeroing because we'll fill all the data. */
14370  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, len / 2);
14371  DUK_ASSERT(buf != NULL);
14372 
14373 #if defined(DUK_USE_HEX_FASTPATH)
14374  p = buf;
14375  len_safe = len & ~0x07U;
14376  for (i = 0; i < len_safe; i += 8) {
14377  t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
14378  ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
14379  chk = t;
14380  p[0] = (duk_uint8_t) t;
14381  t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
14382  ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
14383  chk |= t;
14384  p[1] = (duk_uint8_t) t;
14385  t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
14386  ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
14387  chk |= t;
14388  p[2] = (duk_uint8_t) t;
14389  t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
14390  ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
14391  chk |= t;
14392  p[3] = (duk_uint8_t) t;
14393  p += 4;
14394 
14395  /* Check if any lookup above had a negative result. */
14396  if (DUK_UNLIKELY(chk < 0)) {
14397  goto type_error;
14398  }
14399  }
14400  for (; i < len; i += 2) {
14401  t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
14402  ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
14403  if (DUK_UNLIKELY(t < 0)) {
14404  goto type_error;
14405  }
14406  *p++ = (duk_uint8_t) t;
14407  }
14408 #else /* DUK_USE_HEX_FASTPATH */
14409  for (i = 0; i < len; i += 2) {
14410  /* For invalid characters the value -1 gets extended to
14411  * at least 16 bits. If either nybble is invalid, the
14412  * resulting 't' will be < 0.
14413  */
14414  t = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |
14415  ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
14416  if (DUK_UNLIKELY(t < 0)) {
14417  goto type_error;
14418  }
14419  buf[i >> 1] = (duk_uint8_t) t;
14420  }
14421 #endif /* DUK_USE_HEX_FASTPATH */
14422 
14423  duk_replace(ctx, idx);
14424  return;
14425 
14426  type_error:
14427  DUK_ERROR_TYPE(thr, DUK_STR_DECODE_FAILED);
14428 }
14429 
14430 #if defined(DUK_USE_JSON_SUPPORT)
14431 DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t idx) {
14432 #if defined(DUK_USE_ASSERTIONS)
14433  duk_idx_t top_at_entry;
14434 #endif
14435  const char *ret;
14436 
14437  DUK_ASSERT_CTX_VALID(ctx);
14438 #if defined(DUK_USE_ASSERTIONS)
14439  top_at_entry = duk_get_top(ctx);
14440 #endif
14441 
14442  idx = duk_require_normalize_index(ctx, idx);
14443  duk_bi_json_stringify_helper(ctx,
14444  idx /*idx_value*/,
14445  DUK_INVALID_INDEX /*idx_replacer*/,
14446  DUK_INVALID_INDEX /*idx_space*/,
14447  0 /*flags*/);
14448  DUK_ASSERT(duk_is_string(ctx, -1));
14449  duk_replace(ctx, idx);
14450  ret = duk_get_string(ctx, idx);
14451 
14452  DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
14453 
14454  return ret;
14455 }
14456 
14457 DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t idx) {
14458 #if defined(DUK_USE_ASSERTIONS)
14459  duk_idx_t top_at_entry;
14460 #endif
14461 
14462  DUK_ASSERT_CTX_VALID(ctx);
14463 #if defined(DUK_USE_ASSERTIONS)
14464  top_at_entry = duk_get_top(ctx);
14465 #endif
14466 
14467  idx = duk_require_normalize_index(ctx, idx);
14468  duk_bi_json_parse_helper(ctx,
14469  idx /*idx_value*/,
14470  DUK_INVALID_INDEX /*idx_reviver*/,
14471  0 /*flags*/);
14472  duk_replace(ctx, idx);
14473 
14474  DUK_ASSERT(duk_get_top(ctx) == top_at_entry);
14475 }
14476 #else /* DUK_USE_JSON_SUPPORT */
14477 DUK_EXTERNAL const char *duk_json_encode(duk_context *ctx, duk_idx_t idx) {
14478  DUK_UNREF(idx);
14479  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
14480 }
14481 
14482 DUK_EXTERNAL void duk_json_decode(duk_context *ctx, duk_idx_t idx) {
14483  DUK_UNREF(idx);
14484  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
14485 }
14486 #endif /* DUK_USE_JSON_SUPPORT */
14487 /*
14488  * Compilation and evaluation
14489  */
14490 
14491 /* #include duk_internal.h -> already included */
14492 
14495  duk_size_t src_length; /* should be first on 64-bit platforms */
14496  const duk_uint8_t *src_buffer;
14497  duk_uint_t flags;
14498 };
14499 
14500 /* Eval is just a wrapper now. */
14501 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
14502  duk_uint_t comp_flags;
14503  duk_int_t rc;
14504 
14505  DUK_ASSERT_CTX_VALID(ctx);
14506 
14507  /* Note: strictness is *not* inherited from the current Duktape/C.
14508  * This would be confusing because the current strictness state
14509  * depends on whether we're running inside a Duktape/C activation
14510  * (= strict mode) or outside of any activation (= non-strict mode).
14511  * See tests/api/test-eval-strictness.c for more discussion.
14512  */
14513 
14514  /* [ ... source? filename? ] (depends on flags) */
14515 
14516  comp_flags = flags;
14517  comp_flags |= DUK_COMPILE_EVAL;
14518  rc = duk_compile_raw(ctx, src_buffer, src_length, comp_flags); /* may be safe, or non-safe depending on flags */
14519 
14520  /* [ ... closure/error ] */
14521 
14522  if (rc != DUK_EXEC_SUCCESS) {
14523  rc = DUK_EXEC_ERROR;
14524  goto got_rc;
14525  }
14526 
14527  duk_push_global_object(ctx); /* explicit 'this' binding, see GH-164 */
14528 
14529  if (flags & DUK_COMPILE_SAFE) {
14530  rc = duk_pcall_method(ctx, 0);
14531  } else {
14532  duk_call_method(ctx, 0);
14533  rc = DUK_EXEC_SUCCESS;
14534  }
14535 
14536  /* [ ... result/error ] */
14537 
14538  got_rc:
14539  if (flags & DUK_COMPILE_NORESULT) {
14540  duk_pop(ctx);
14541  }
14542 
14543  return rc;
14544 }
14545 
14546 /* Helper which can be called both directly and with duk_safe_call(). */
14547 DUK_LOCAL duk_ret_t duk__do_compile(duk_context *ctx, void *udata) {
14548  duk_hthread *thr = (duk_hthread *) ctx;
14549  duk__compile_raw_args *comp_args;
14550  duk_uint_t flags;
14551  duk_small_uint_t comp_flags;
14552  duk_hcompfunc *h_templ;
14553 
14554  DUK_ASSERT_CTX_VALID(ctx);
14555  DUK_ASSERT(udata != NULL);
14556 
14557  /* Note: strictness is not inherited from the current Duktape/C
14558  * context. Otherwise it would not be possible to compile
14559  * non-strict code inside a Duktape/C activation (which is
14560  * always strict now). See tests/api/test-eval-strictness.c
14561  * for discussion.
14562  */
14563 
14564  /* [ ... source? filename? ] (depends on flags) */
14565 
14566  comp_args = (duk__compile_raw_args *) udata;
14567  flags = comp_args->flags;
14568 
14569  if (flags & DUK_COMPILE_NOFILENAME) {
14570  /* Automatic filename: 'eval' or 'input'. */
14571  duk_push_hstring_stridx(ctx, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
14572  }
14573 
14574  /* [ ... source? filename ] */
14575 
14576  if (!comp_args->src_buffer) {
14577  duk_hstring *h_sourcecode;
14578 
14579  h_sourcecode = duk_get_hstring(ctx, -2);
14580  if ((flags & DUK_COMPILE_NOSOURCE) || /* args incorrect */
14581  (h_sourcecode == NULL)) { /* e.g. duk_push_string_file_raw() pushed undefined */
14582  DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
14583  }
14584  DUK_ASSERT(h_sourcecode != NULL);
14585  comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
14586  comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
14587  }
14588  DUK_ASSERT(comp_args->src_buffer != NULL);
14589 
14590  /* XXX: unnecessary translation of flags */
14591  comp_flags = 0;
14592  if (flags & DUK_COMPILE_EVAL) {
14593  comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
14594  }
14595  if (flags & DUK_COMPILE_FUNCTION) {
14596  comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
14597  DUK_JS_COMPILE_FLAG_FUNCEXPR;
14598  }
14599  if (flags & DUK_COMPILE_STRICT) {
14600  comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
14601  }
14602 
14603  /* [ ... source? filename ] */
14604 
14605  duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
14606 
14607  /* [ ... source? func_template ] */
14608 
14609  if (flags & DUK_COMPILE_NOSOURCE) {
14610  ;
14611  } else {
14612  duk_remove_m2(ctx);
14613  }
14614 
14615  /* [ ... func_template ] */
14616 
14617  h_templ = (duk_hcompfunc *) duk_known_hobject(ctx, -1);
14618  duk_js_push_closure(thr,
14619  h_templ,
14620  thr->builtins[DUK_BIDX_GLOBAL_ENV],
14621  thr->builtins[DUK_BIDX_GLOBAL_ENV],
14622  1 /*add_auto_proto*/);
14623  duk_remove_m2(ctx); /* -> [ ... closure ] */
14624 
14625  /* [ ... closure ] */
14626 
14627  return 1;
14628 }
14629 
14630 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
14631  duk__compile_raw_args comp_args_alloc;
14632  duk__compile_raw_args *comp_args = &comp_args_alloc;
14633 
14634  DUK_ASSERT_CTX_VALID(ctx);
14635 
14636  if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
14637  /* String length is computed here to avoid multiple evaluation
14638  * of a macro argument in the calling side.
14639  */
14640  src_length = DUK_STRLEN(src_buffer);
14641  }
14642 
14643  comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
14644  comp_args->src_length = src_length;
14645  comp_args->flags = flags;
14646 
14647  /* [ ... source? filename? ] (depends on flags) */
14648 
14649  if (flags & DUK_COMPILE_SAFE) {
14650  duk_int_t rc;
14651  duk_int_t nargs;
14652  duk_int_t nrets = 1;
14653 
14654  /* Arguments can be: [ source? filename? &comp_args] so that
14655  * nargs is 1 to 3. Call site encodes the correct nargs count
14656  * directly into flags.
14657  */
14658  nargs = flags & 0x07;
14659  DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
14660  ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
14661  rc = duk_safe_call(ctx, duk__do_compile, (void *) comp_args, nargs, nrets);
14662 
14663  /* [ ... closure ] */
14664  return rc;
14665  }
14666 
14667  (void) duk__do_compile(ctx, (void *) comp_args);
14668 
14669  /* [ ... closure ] */
14670  return DUK_EXEC_SUCCESS;
14671 }
14672 /*
14673  * Debugging related API calls
14674  */
14675 
14676 /* #include duk_internal.h -> already included */
14677 
14678 #if defined(DUK_USE_JSON_SUPPORT)
14679 DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) {
14680  duk_idx_t idx;
14681  duk_idx_t top;
14682 
14683  DUK_ASSERT_CTX_VALID(ctx);
14684 
14685  /* We don't duk_require_stack() here now, but rely on the caller having
14686  * enough space.
14687  */
14688 
14689  top = duk_get_top(ctx);
14690  duk_push_array(ctx);
14691  for (idx = 0; idx < top; idx++) {
14692  duk_dup(ctx, idx);
14693  duk_put_prop_index(ctx, -2, idx);
14694  }
14695 
14696  /* XXX: conversion errors should not propagate outwards.
14697  * Perhaps values need to be coerced individually?
14698  */
14699  duk_bi_json_stringify_helper(ctx,
14700  duk_get_top_index(ctx), /*idx_value*/
14701  DUK_INVALID_INDEX, /*idx_replacer*/
14702  DUK_INVALID_INDEX, /*idx_space*/
14703  DUK_JSON_FLAG_EXT_CUSTOM |
14704  DUK_JSON_FLAG_ASCII_ONLY |
14705  DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
14706 
14707  duk_push_sprintf(ctx, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(ctx, -1));
14708  duk_replace(ctx, -3); /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
14709  duk_pop(ctx);
14710  DUK_ASSERT(duk_is_string(ctx, -1));
14711 }
14712 #else /* DUK_USE_JSON_SUPPORT */
14713 DUK_EXTERNAL void duk_push_context_dump(duk_context *ctx) {
14714  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
14715 }
14716 #endif /* DUK_USE_JSON_SUPPORT */
14717 
14718 #if defined(DUK_USE_DEBUGGER_SUPPORT)
14719 
14720 DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
14721  duk_debug_read_function read_cb,
14722  duk_debug_write_function write_cb,
14723  duk_debug_peek_function peek_cb,
14724  duk_debug_read_flush_function read_flush_cb,
14725  duk_debug_write_flush_function write_flush_cb,
14726  duk_debug_request_function request_cb,
14727  duk_debug_detached_function detached_cb,
14728  void *udata) {
14729  duk_hthread *thr = (duk_hthread *) ctx;
14730  duk_heap *heap;
14731  const char *str;
14732  duk_size_t len;
14733 
14734  /* XXX: should there be an error or an automatic detach if
14735  * already attached?
14736  */
14737 
14738  DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
14739 
14740  DUK_ASSERT_CTX_VALID(ctx);
14741  DUK_ASSERT(read_cb != NULL);
14742  DUK_ASSERT(write_cb != NULL);
14743  /* Other callbacks are optional. */
14744 
14745  heap = thr->heap;
14746  heap->dbg_read_cb = read_cb;
14747  heap->dbg_write_cb = write_cb;
14748  heap->dbg_peek_cb = peek_cb;
14749  heap->dbg_read_flush_cb = read_flush_cb;
14750  heap->dbg_write_flush_cb = write_flush_cb;
14751  heap->dbg_request_cb = request_cb;
14752  heap->dbg_detached_cb = detached_cb;
14753  heap->dbg_udata = udata;
14754  heap->dbg_have_next_byte = 0;
14755 
14756  /* Start in paused state. */
14757  heap->dbg_processing = 0;
14758  DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
14759  heap->dbg_state_dirty = 1;
14760  heap->dbg_force_restart = 0;
14761  heap->dbg_step_type = 0;
14762  heap->dbg_step_thread = NULL;
14763  heap->dbg_step_csindex = 0;
14764  heap->dbg_step_startline = 0;
14765  heap->dbg_exec_counter = 0;
14766  heap->dbg_last_counter = 0;
14767  heap->dbg_last_time = 0.0;
14768 
14769  /* Send version identification and flush right afterwards. Note that
14770  * we must write raw, unframed bytes here.
14771  */
14772  duk_push_sprintf(ctx, "%ld %ld %s %s\n",
14773  (long) DUK_DEBUG_PROTOCOL_VERSION,
14774  (long) DUK_VERSION,
14775  (const char *) DUK_GIT_DESCRIBE,
14776  (const char *) DUK_USE_TARGET_INFO);
14777  str = duk_get_lstring(ctx, -1, &len);
14778  DUK_ASSERT(str != NULL);
14779  duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
14780  duk_debug_write_flush(thr);
14781  duk_pop(ctx);
14782 }
14783 
14784 DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
14785  duk_hthread *thr;
14786 
14787  DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
14788 
14789  DUK_ASSERT_CTX_VALID(ctx);
14790  thr = (duk_hthread *) ctx;
14791  DUK_ASSERT(thr != NULL);
14792  DUK_ASSERT(thr->heap != NULL);
14793 
14794  /* Can be called multiple times with no harm. */
14795  duk_debug_do_detach(thr->heap);
14796 }
14797 
14798 DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
14799  duk_hthread *thr;
14800  duk_bool_t processed_messages;
14801 
14802  DUK_ASSERT_CTX_VALID(ctx);
14803  thr = (duk_hthread *) ctx;
14804  DUK_ASSERT(thr != NULL);
14805  DUK_ASSERT(thr->heap != NULL);
14806 
14807  if (!DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
14808  return;
14809  }
14810  if (thr->callstack_top > 0 || thr->heap->dbg_processing) {
14811  /* Calling duk_debugger_cooperate() while Duktape is being
14812  * called into is not supported. This is not a 100% check
14813  * but prevents any damage in most cases.
14814  */
14815  return;
14816  }
14817 
14818  processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
14819  DUK_UNREF(processed_messages);
14820 }
14821 
14822 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues) {
14823  duk_hthread *thr;
14824  duk_idx_t top;
14825  duk_idx_t idx;
14826  duk_bool_t ret = 0;
14827 
14828  DUK_ASSERT_CTX_VALID(ctx);
14829  thr = (duk_hthread *) ctx;
14830  DUK_ASSERT(thr != NULL);
14831  DUK_ASSERT(thr->heap != NULL);
14832 
14833  DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
14834 
14835  top = duk_get_top(ctx);
14836  if (top < nvalues) {
14837  DUK_ERROR_RANGE(thr, "not enough stack values for notify");
14838  return ret; /* unreachable */
14839  }
14840  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
14841  duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
14842  for (idx = top - nvalues; idx < top; idx++) {
14843  duk_tval *tv = DUK_GET_TVAL_POSIDX(ctx, idx);
14844  duk_debug_write_tval(thr, tv);
14845  }
14846  duk_debug_write_eom(thr);
14847 
14848  /* Return non-zero (true) if we have a good reason to believe
14849  * the notify was delivered; if we're still attached at least
14850  * a transport error was not indicated by the transport write
14851  * callback. This is not a 100% guarantee of course.
14852  */
14853  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
14854  ret = 1;
14855  }
14856  }
14857  duk_pop_n(ctx, nvalues);
14858  return ret;
14859 }
14860 
14861 DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx) {
14862  duk_hthread *thr;
14863 
14864  DUK_ASSERT_CTX_VALID(ctx);
14865  thr = (duk_hthread *) ctx;
14866  DUK_ASSERT(thr != NULL);
14867  DUK_ASSERT(thr->heap != NULL);
14868 
14869  DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
14870 
14871  /* Treat like a debugger statement: ignore when not attached. */
14872  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
14873  DUK_HEAP_SET_PAUSED(thr->heap);
14874 
14875  /* Pause on the next opcode executed. This is always safe to do even
14876  * inside the debugger message loop: the interrupt counter will be reset
14877  * to its proper value when the message loop exits.
14878  */
14879  thr->interrupt_init = 1;
14880  thr->interrupt_counter = 0;
14881  }
14882 }
14883 
14884 #else /* DUK_USE_DEBUGGER_SUPPORT */
14885 
14886 DUK_EXTERNAL void duk_debugger_attach(duk_context *ctx,
14887  duk_debug_read_function read_cb,
14888  duk_debug_write_function write_cb,
14889  duk_debug_peek_function peek_cb,
14890  duk_debug_read_flush_function read_flush_cb,
14891  duk_debug_write_flush_function write_flush_cb,
14892  duk_debug_request_function request_cb,
14893  duk_debug_detached_function detached_cb,
14894  void *udata) {
14895  DUK_ASSERT_CTX_VALID(ctx);
14896  DUK_UNREF(read_cb);
14897  DUK_UNREF(write_cb);
14898  DUK_UNREF(peek_cb);
14899  DUK_UNREF(read_flush_cb);
14900  DUK_UNREF(write_flush_cb);
14901  DUK_UNREF(request_cb);
14902  DUK_UNREF(detached_cb);
14903  DUK_UNREF(udata);
14904  DUK_ERROR_TYPE((duk_hthread *) ctx, "no debugger support");
14905 }
14906 
14907 DUK_EXTERNAL void duk_debugger_detach(duk_context *ctx) {
14908  DUK_ASSERT_CTX_VALID(ctx);
14909  DUK_ERROR_TYPE((duk_hthread *) ctx, "no debugger support");
14910 }
14911 
14912 DUK_EXTERNAL void duk_debugger_cooperate(duk_context *ctx) {
14913  /* nop */
14914  DUK_ASSERT_CTX_VALID(ctx);
14915  DUK_UNREF(ctx);
14916 }
14917 
14918 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues) {
14919  duk_idx_t top;
14920 
14921  DUK_ASSERT_CTX_VALID(ctx);
14922 
14923  top = duk_get_top(ctx);
14924  if (top < nvalues) {
14925  DUK_ERROR_RANGE_INVALID_COUNT((duk_hthread *) ctx);
14926  return 0; /* unreachable */
14927  }
14928 
14929  /* No debugger support, just pop values. */
14930  duk_pop_n(ctx, nvalues);
14931  return 0;
14932 }
14933 
14934 DUK_EXTERNAL void duk_debugger_pause(duk_context *ctx) {
14935  /* Treat like debugger statement: nop */
14936  DUK_ASSERT_CTX_VALID(ctx);
14937  DUK_UNREF(ctx);
14938 }
14939 
14940 #endif /* DUK_USE_DEBUGGER_SUPPORT */
14941 /*
14942  * Heap creation and destruction
14943  */
14944 
14945 /* #include duk_internal.h -> already included */
14946 
14948 
14950  duk_ljstate lj;
14951  duk_bool_t handling_error;
14952  duk_hthread *curr_thread;
14953  duk_int_t call_recursion_depth;
14954 };
14955 
14956 DUK_EXTERNAL
14957 duk_context *duk_create_heap(duk_alloc_function alloc_func,
14958  duk_realloc_function realloc_func,
14959  duk_free_function free_func,
14960  void *heap_udata,
14961  duk_fatal_function fatal_handler) {
14962  duk_heap *heap = NULL;
14963  duk_context *ctx;
14964 
14965  /* Assume that either all memory funcs are NULL or non-NULL, mixed
14966  * cases will now be unsafe.
14967  */
14968 
14969  /* XXX: just assert non-NULL values here and make caller arguments
14970  * do the defaulting to the default implementations (smaller code)?
14971  */
14972 
14973  if (!alloc_func) {
14974  DUK_ASSERT(realloc_func == NULL);
14975  DUK_ASSERT(free_func == NULL);
14976 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
14977  alloc_func = duk_default_alloc_function;
14978  realloc_func = duk_default_realloc_function;
14979  free_func = duk_default_free_function;
14980 #else
14981  DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
14982  return NULL;
14983 #endif
14984  } else {
14985  DUK_ASSERT(realloc_func != NULL);
14986  DUK_ASSERT(free_func != NULL);
14987  }
14988 
14989  if (!fatal_handler) {
14990  fatal_handler = duk_default_fatal_handler;
14991  }
14992 
14993  DUK_ASSERT(alloc_func != NULL);
14994  DUK_ASSERT(realloc_func != NULL);
14995  DUK_ASSERT(free_func != NULL);
14996  DUK_ASSERT(fatal_handler != NULL);
14997 
14998  heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
14999  if (!heap) {
15000  return NULL;
15001  }
15002  ctx = (duk_context *) heap->heap_thread;
15003  DUK_ASSERT(ctx != NULL);
15004  DUK_ASSERT(((duk_hthread *) ctx)->heap != NULL);
15005  return ctx;
15006 }
15007 
15008 DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx) {
15009  duk_hthread *thr = (duk_hthread *) ctx;
15010  duk_heap *heap;
15011 
15012  if (!ctx) {
15013  return;
15014  }
15015  heap = thr->heap;
15016  DUK_ASSERT(heap != NULL);
15017 
15018  duk_heap_free(heap);
15019 }
15020 
15021 DUK_EXTERNAL void duk_suspend(duk_context *ctx, duk_thread_state *state) {
15022  duk_hthread *thr = (duk_hthread *) ctx;
15023  duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
15024  duk_heap *heap;
15025  duk_ljstate *lj;
15026 
15027  DUK_ASSERT_CTX_VALID(ctx);
15028  DUK_ASSERT(thr != NULL);
15029  DUK_ASSERT(thr->heap != NULL);
15030  DUK_ASSERT(state != NULL); /* unvalidated */
15031 
15032  heap = thr->heap;
15033  lj = &heap->lj;
15034 
15035  duk_push_tval(ctx, &lj->value1);
15036  duk_push_tval(ctx, &lj->value2);
15037 
15038  DUK_MEMCPY((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
15039  snapshot->handling_error = heap->handling_error;
15040  snapshot->curr_thread = heap->curr_thread;
15041  snapshot->call_recursion_depth = heap->call_recursion_depth;
15042 
15043  lj->jmpbuf_ptr = NULL;
15044  lj->type = DUK_LJ_TYPE_UNKNOWN;
15045  DUK_TVAL_SET_UNDEFINED(&lj->value1);
15046  DUK_TVAL_SET_UNDEFINED(&lj->value2);
15047  heap->handling_error = 0;
15048  heap->curr_thread = NULL;
15049  heap->call_recursion_depth = 0;
15050 }
15051 
15052 DUK_EXTERNAL void duk_resume(duk_context *ctx, const duk_thread_state *state) {
15053  duk_hthread *thr = (duk_hthread *) ctx;
15054  const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
15055  duk_heap *heap;
15056 
15057  DUK_ASSERT_CTX_VALID(ctx);
15058  DUK_ASSERT(thr != NULL);
15059  DUK_ASSERT(thr->heap != NULL);
15060  DUK_ASSERT(state != NULL); /* unvalidated */
15061 
15062  heap = thr->heap;
15063 
15064  DUK_MEMCPY((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
15065  heap->handling_error = snapshot->handling_error;
15066  heap->curr_thread = snapshot->curr_thread;
15067  heap->call_recursion_depth = snapshot->call_recursion_depth;
15068 
15069  duk_pop_2(ctx);
15070 }
15071 
15072 /* XXX: better place for this */
15073 DUK_EXTERNAL void duk_set_global_object(duk_context *ctx) {
15074  duk_hthread *thr = (duk_hthread *) ctx;
15075  duk_hobject *h_glob;
15076  duk_hobject *h_prev_glob;
15077  duk_hobject *h_env;
15078  duk_hobject *h_prev_env;
15079 
15080  DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(ctx, -1)));
15081 
15082  h_glob = duk_require_hobject(ctx, -1);
15083  DUK_ASSERT(h_glob != NULL);
15084 
15085  /*
15086  * Replace global object.
15087  */
15088 
15089  h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
15090  DUK_UNREF(h_prev_glob);
15091  thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
15092  DUK_HOBJECT_INCREF(thr, h_glob);
15093  DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob); /* side effects, in theory (referenced by global env) */
15094 
15095  /*
15096  * Replace lexical environment for global scope
15097  *
15098  * Create a new object environment for the global lexical scope.
15099  * We can't just reset the _Target property of the current one,
15100  * because the lexical scope is shared by other threads with the
15101  * same (initial) built-ins.
15102  */
15103 
15104  h_env = duk_push_object_helper(ctx,
15105  DUK_HOBJECT_FLAG_EXTENSIBLE |
15106  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
15107  -1); /* no prototype, updated below */
15108  DUK_ASSERT(h_env != NULL);
15109 
15110  duk_dup_m2(ctx);
15111  duk_dup_m3(ctx);
15112  duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
15113  duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
15114 
15115  /* [ ... new_glob new_env ] */
15116 
15117  h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
15118  thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_env;
15119  DUK_HOBJECT_INCREF(thr, h_env);
15120  DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env); /* side effects */
15121  DUK_UNREF(h_env); /* without refcounts */
15122  DUK_UNREF(h_prev_env);
15123 
15124  /* [ ... new_glob new_env ] */
15125 
15126  duk_pop_2(ctx);
15127 
15128  /* [ ... ] */
15129 }
15130 /*
15131  * Inspection
15132  */
15133 
15134 /* #include duk_internal.h -> already included */
15135 
15136 /* For footprint efficient multiple value setting: arrays are much better than
15137  * varargs, format string with parsing is often better than string pointer arrays.
15138  */
15139 DUK_LOCAL void duk__inspect_multiple_uint(duk_context *ctx, const char *fmt, duk_int_t *vals) {
15140  duk_int_t val;
15141  const char *p;
15142  const char *p_curr;
15143  duk_size_t len;
15144 
15145  for (p = fmt;;) {
15146  len = DUK_STRLEN(p);
15147  p_curr = p;
15148  p += len + 1;
15149  if (len == 0) {
15150  /* Double NUL (= empty key) terminates. */
15151  break;
15152  }
15153  val = *vals++;
15154  if (val >= 0) {
15155  /* Negative values are markers to skip key. */
15156  duk_push_string(ctx, p_curr);
15157  duk_push_uint(ctx, val);
15158  duk_put_prop(ctx, -3);
15159  }
15160  }
15161 }
15162 
15163 /* Raw helper to extract internal information / statistics about a value.
15164  * The return value is an object with properties that are version specific.
15165  * The properties must not expose anything that would lead to security
15166  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
15167  * Currently only counts and sizes and such are given so there shouldn't
15168  * be security implications.
15169  */
15170 
15171 #define DUK__IDX_TYPE 0
15172 #define DUK__IDX_ITAG 1
15173 #define DUK__IDX_REFC 2
15174 #define DUK__IDX_HBYTES 3
15175 #define DUK__IDX_CLASS 4
15176 #define DUK__IDX_PBYTES 5
15177 #define DUK__IDX_ESIZE 6
15178 #define DUK__IDX_ENEXT 7
15179 #define DUK__IDX_ASIZE 8
15180 #define DUK__IDX_HSIZE 9
15181 #define DUK__IDX_BCBYTES 10
15182 #define DUK__IDX_DBYTES 11
15183 #define DUK__IDX_TSTATE 12
15184 #define DUK__IDX_VARIANT 13
15185 
15186 DUK_EXTERNAL void duk_inspect_value(duk_context *ctx, duk_idx_t idx) {
15187  duk_hthread *thr = (duk_hthread *) ctx;
15188  duk_tval *tv;
15189  duk_heaphdr *h;
15190  /* The temporary values should be in an array rather than individual
15191  * variables which (in practice) ensures that the compiler won't map
15192  * them to registers and emit a lot of unnecessary shuffling code.
15193  */
15194  duk_int_t vals[14];
15195 
15196  DUK_UNREF(thr);
15197 
15198  tv = duk_get_tval_or_unused(ctx, idx);
15199  h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
15200 
15201  /* Assume two's complement and set everything to -1. */
15202  DUK_MEMSET((void *) &vals, (int) 0xff, sizeof(vals));
15203  DUK_ASSERT(vals[DUK__IDX_TYPE] == -1); /* spot check one */
15204 
15205  duk_push_bare_object(ctx);
15206 
15207  vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
15208  vals[DUK__IDX_ITAG] = (duk_uint_t) DUK_TVAL_GET_TAG(tv);
15209 
15210  if (h == NULL) {
15211  goto finish;
15212  }
15213  duk_push_pointer(ctx, (void *) h);
15214  duk_put_prop_string(ctx, -2, "hptr");
15215 
15216 #if 0
15217  /* Covers a lot of information, e.g. buffer and string variants. */
15218  duk_push_uint(ctx, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
15219  duk_put_prop_string(ctx, -2, "hflags");
15220 #endif
15221 
15222 #if defined(DUK_USE_REFERENCE_COUNTING)
15223  vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
15224 #endif
15225  vals[DUK__IDX_VARIANT] = 0;
15226 
15227  /* Heaphdr size and additional allocation size, followed by
15228  * type specific stuff (with varying value count).
15229  */
15230  switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
15231  case DUK_HTYPE_STRING: {
15232  duk_hstring *h_str = (duk_hstring *) h;
15233  vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
15234 #if defined(DUK_USE_HSTRING_EXTDATA)
15235  if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
15236  vals[DUK__IDX_VARIANT] = 1;
15237  }
15238 #endif
15239  break;
15240  }
15241  case DUK_HTYPE_OBJECT: {
15242  duk_hobject *h_obj = (duk_hobject *) h;
15243 
15244  /* XXX: variants here are maybe pointless; class is enough? */
15245  if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
15246  vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
15247  } else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
15248  vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
15249  } else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
15250  vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
15251  } else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
15252  vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
15253  vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
15254 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
15255  } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
15256  vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
15257  /* XXX: some size information */
15258 #endif
15259  } else {
15260  vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
15261  }
15262 
15263  vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
15264  vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj),
15265  vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
15266  vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
15267  vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
15268  vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
15269 
15270  /* Note: e_next indicates the number of gc-reachable entries
15271  * in the entry part, and also indicates the index where the
15272  * next new property would be inserted. It does *not* indicate
15273  * the number of non-NULL keys present in the object. That
15274  * value could be counted separately but requires a pass through
15275  * the key list.
15276  */
15277 
15278  if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
15279  duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
15280  vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
15281  }
15282  break;
15283  }
15284  case DUK_HTYPE_BUFFER: {
15285  duk_hbuffer *h_buf = (duk_hbuffer *) h;
15286 
15287  if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
15288  if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
15289  vals[DUK__IDX_VARIANT] = 2; /* buffer variant 2: external */
15290  vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
15291  } else {
15292  /* When alloc_size == 0 the second allocation may not
15293  * actually exist.
15294  */
15295  vals[DUK__IDX_VARIANT] = 1; /* buffer variant 1: dynamic */
15296  vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
15297  }
15298  vals[DUK__IDX_DBYTES] = (duk_uint_t) (DUK_HBUFFER_GET_SIZE(h_buf));
15299  } else {
15300  DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0); /* buffer variant 0: fixed */
15301  vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
15302  }
15303  break;
15304  }
15305  }
15306 
15307  finish:
15308  duk__inspect_multiple_uint(ctx,
15309  "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
15310  "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
15311  "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
15312  (duk_int_t *) &vals);
15313 }
15314 
15315 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_context *ctx, duk_int_t level) {
15316  duk_hthread *thr = (duk_hthread *) ctx;
15317  duk_activation *act;
15318  duk_uint_fast32_t pc;
15319  duk_uint_fast32_t line;
15320 
15321  DUK_ASSERT_CTX_VALID(ctx);
15322 
15323  /* -1 = top callstack entry, callstack[callstack_top - 1]
15324  * -callstack_top = bottom callstack entry, callstack[0]
15325  */
15326  if (level >= 0 || -level > (duk_int_t) thr->callstack_top) {
15327  duk_push_undefined(ctx);
15328  return;
15329  }
15330  duk_push_bare_object(ctx);
15331  DUK_ASSERT(level >= -((duk_int_t) thr->callstack_top) && level <= -1);
15332 
15333  act = thr->callstack + thr->callstack_top + level;
15334  /* Relevant PC is just before current one because PC is
15335  * post-incremented. This should match what error augment
15336  * code does.
15337  */
15338  pc = duk_hthread_get_act_prev_pc(thr, act);
15339 
15340  duk_push_tval(ctx, &act->tv_func);
15341 
15342  duk_push_uint(ctx, (duk_uint_t) pc);
15343  duk_put_prop_stridx_short(ctx, -3, DUK_STRIDX_PC);
15344 
15345 #if defined(DUK_USE_PC2LINE)
15346  line = duk_hobject_pc2line_query(ctx, -1, pc);
15347 #else
15348  line = 0;
15349 #endif
15350  duk_push_uint(ctx, (duk_uint_t) line);
15351  duk_put_prop_stridx_short(ctx, -3, DUK_STRIDX_LINE_NUMBER);
15352 
15353  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_LC_FUNCTION);
15354  /* Providing access to e.g. act->lex_env would be dangerous: these
15355  * internal structures must never be accessible to the application.
15356  * Duktape relies on them having consistent data, and this consistency
15357  * is only asserted for, not checked for.
15358  */
15359 }
15360 
15361 /* automatic undefs */
15362 #undef DUK__IDX_ASIZE
15363 #undef DUK__IDX_BCBYTES
15364 #undef DUK__IDX_CLASS
15365 #undef DUK__IDX_DBYTES
15366 #undef DUK__IDX_ENEXT
15367 #undef DUK__IDX_ESIZE
15368 #undef DUK__IDX_HBYTES
15369 #undef DUK__IDX_HSIZE
15370 #undef DUK__IDX_ITAG
15371 #undef DUK__IDX_PBYTES
15372 #undef DUK__IDX_REFC
15373 #undef DUK__IDX_TSTATE
15374 #undef DUK__IDX_TYPE
15375 #undef DUK__IDX_VARIANT
15376 /*
15377  * Memory calls.
15378  */
15379 
15380 /* #include duk_internal.h -> already included */
15381 
15382 DUK_EXTERNAL void *duk_alloc_raw(duk_context *ctx, duk_size_t size) {
15383  duk_hthread *thr = (duk_hthread *) ctx;
15384 
15385  DUK_ASSERT_CTX_VALID(ctx);
15386 
15387  return DUK_ALLOC_RAW(thr->heap, size);
15388 }
15389 
15390 DUK_EXTERNAL void duk_free_raw(duk_context *ctx, void *ptr) {
15391  duk_hthread *thr = (duk_hthread *) ctx;
15392 
15393  DUK_ASSERT_CTX_VALID(ctx);
15394 
15395  DUK_FREE_RAW(thr->heap, ptr);
15396 }
15397 
15398 DUK_EXTERNAL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size) {
15399  duk_hthread *thr = (duk_hthread *) ctx;
15400 
15401  DUK_ASSERT_CTX_VALID(ctx);
15402 
15403  return DUK_REALLOC_RAW(thr->heap, ptr, size);
15404 }
15405 
15406 DUK_EXTERNAL void *duk_alloc(duk_context *ctx, duk_size_t size) {
15407  duk_hthread *thr = (duk_hthread *) ctx;
15408 
15409  DUK_ASSERT_CTX_VALID(ctx);
15410 
15411  return DUK_ALLOC(thr->heap, size);
15412 }
15413 
15414 DUK_EXTERNAL void duk_free(duk_context *ctx, void *ptr) {
15415  duk_hthread *thr = (duk_hthread *) ctx;
15416 
15417  DUK_ASSERT_CTX_VALID(ctx);
15418 
15419  DUK_FREE(thr->heap, ptr);
15420 }
15421 
15422 DUK_EXTERNAL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size) {
15423  duk_hthread *thr = (duk_hthread *) ctx;
15424 
15425  DUK_ASSERT_CTX_VALID(ctx);
15426 
15427  /*
15428  * Note: since this is an exposed API call, there should be
15429  * no way a mark-and-sweep could have a side effect on the
15430  * memory allocation behind 'ptr'; the pointer should never
15431  * be something that Duktape wants to change.
15432  *
15433  * Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
15434  * have the storage location here anyway).
15435  */
15436 
15437  return DUK_REALLOC(thr->heap, ptr, size);
15438 }
15439 
15440 DUK_EXTERNAL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs) {
15441  duk_hthread *thr = (duk_hthread *) ctx;
15442  duk_heap *heap;
15443 
15444  DUK_ASSERT_CTX_VALID(ctx);
15445  DUK_ASSERT(out_funcs != NULL);
15446  DUK_ASSERT(thr != NULL);
15447  DUK_ASSERT(thr->heap != NULL);
15448 
15449  heap = thr->heap;
15450  out_funcs->alloc_func = heap->alloc_func;
15451  out_funcs->realloc_func = heap->realloc_func;
15452  out_funcs->free_func = heap->free_func;
15453  out_funcs->udata = heap->heap_udata;
15454 }
15455 
15456 DUK_EXTERNAL void duk_gc(duk_context *ctx, duk_uint_t flags) {
15457  duk_hthread *thr = (duk_hthread *) ctx;
15458  duk_heap *heap;
15459  duk_small_uint_t ms_flags;
15460 
15461  DUK_ASSERT_CTX_VALID(ctx);
15462  heap = thr->heap;
15463  DUK_ASSERT(heap != NULL);
15464 
15465  DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
15466  DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY); /* Compact flag is 1:1 with emergency flag which forces compaction. */
15467  ms_flags = (duk_small_uint_t) flags;
15468  duk_heap_mark_and_sweep(heap, ms_flags);
15469 }
15470 /*
15471  * Object handling: property access and other support functions.
15472  */
15473 
15474 /* #include duk_internal.h -> already included */
15475 
15476 /*
15477  * Property handling
15478  *
15479  * The API exposes only the most common property handling functions.
15480  * The caller can invoke Ecmascript built-ins for full control (e.g.
15481  * defineProperty, getOwnPropertyDescriptor).
15482  */
15483 
15484 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx) {
15485  duk_hthread *thr = (duk_hthread *) ctx;
15486  duk_tval *tv_obj;
15487  duk_tval *tv_key;
15488  duk_bool_t rc;
15489 
15490  DUK_ASSERT_CTX_VALID(ctx);
15491 
15492  /* Note: copying tv_obj and tv_key to locals to shield against a valstack
15493  * resize is not necessary for a property get right now.
15494  */
15495 
15496  tv_obj = duk_require_tval(ctx, obj_idx);
15497  tv_key = duk_require_tval(ctx, -1);
15498 
15499  rc = duk_hobject_getprop(thr, tv_obj, tv_key);
15500  DUK_ASSERT(rc == 0 || rc == 1);
15501  /* a value is left on stack regardless of rc */
15502 
15503  duk_remove_m2(ctx); /* remove key */
15504  return rc; /* 1 if property found, 0 otherwise */
15505 }
15506 
15507 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
15508  DUK_ASSERT_CTX_VALID(ctx);
15509  DUK_ASSERT(key != NULL);
15510 
15511  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15512  duk_push_string(ctx, key);
15513  return duk_get_prop(ctx, obj_idx);
15514 }
15515 
15516 DUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
15517  DUK_ASSERT_CTX_VALID(ctx);
15518  DUK_ASSERT(key != NULL);
15519 
15520  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15521  duk_push_lstring(ctx, key, key_len);
15522  return duk_get_prop(ctx, obj_idx);
15523 }
15524 
15525 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
15526  DUK_ASSERT_CTX_VALID(ctx);
15527 
15528  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15529  duk_push_uarridx(ctx, arr_idx);
15530  return duk_get_prop(ctx, obj_idx);
15531 }
15532 
15533 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx) {
15534  duk_hthread *thr = (duk_hthread *) ctx;
15535 
15536  DUK_ASSERT_CTX_VALID(ctx);
15537  DUK_ASSERT_STRIDX_VALID(stridx);
15538  DUK_UNREF(thr);
15539 
15540  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15541  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
15542  return duk_get_prop(ctx, obj_idx);
15543 }
15544 
15545 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args) {
15546  return duk_get_prop_stridx(ctx, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
15547  (duk_small_uint_t) (packed_args & 0xffffUL));
15548 }
15549 
15550 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop) {
15551  duk_bool_t rc;
15552 
15553  DUK_ASSERT_CTX_VALID(ctx);
15554  DUK_ASSERT_STRIDX_VALID(stridx);
15555 
15556  rc = duk_get_prop_stridx(ctx, obj_idx, stridx);
15557  if (out_has_prop) {
15558  *out_has_prop = rc;
15559  }
15560  rc = duk_to_boolean(ctx, -1);
15561  DUK_ASSERT(rc == 0 || rc == 1);
15562  duk_pop(ctx);
15563  return rc;
15564 }
15565 
15566 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t idx_key) {
15567  duk_hthread *thr = (duk_hthread *) ctx;
15568  duk_tval *tv_obj;
15569  duk_tval *tv_key;
15570  duk_tval *tv_val;
15571  duk_small_int_t throw_flag;
15572  duk_bool_t rc;
15573 
15574  /* Note: copying tv_obj and tv_key to locals to shield against a valstack
15575  * resize is not necessary for a property put right now (putprop protects
15576  * against it internally).
15577  */
15578 
15579  /* Key and value indices are either (-2, -1) or (-1, -2). Given idx_key,
15580  * idx_val is always (idx_key ^ 0x01).
15581  */
15582  DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
15583  (idx_key == -1 && (idx_key ^ 1) == -2));
15584  /* XXX: Direct access; faster validation. */
15585  tv_obj = duk_require_tval(ctx, obj_idx);
15586  tv_key = duk_require_tval(ctx, idx_key);
15587  tv_val = duk_require_tval(ctx, idx_key ^ 1);
15588  throw_flag = duk_is_strict_call(ctx);
15589 
15590  rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
15591  DUK_ASSERT(rc == 0 || rc == 1);
15592 
15593  duk_pop_2(ctx); /* remove key and value */
15594  return rc; /* 1 if property found, 0 otherwise */
15595 }
15596 
15597 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx) {
15598  DUK_ASSERT_CTX_VALID(ctx);
15599  return duk__put_prop_shared(ctx, obj_idx, -2);
15600 }
15601 
15602 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
15603  DUK_ASSERT_CTX_VALID(ctx);
15604  DUK_ASSERT(key != NULL);
15605 
15606  /* Careful here and with other duk_put_prop_xxx() helpers: the
15607  * target object and the property value may be in the same value
15608  * stack slot (unusual, but still conceptually clear).
15609  */
15610  obj_idx = duk_normalize_index(ctx, obj_idx);
15611  (void) duk_push_string(ctx, key);
15612  return duk__put_prop_shared(ctx, obj_idx, -1);
15613 }
15614 
15615 DUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
15616  DUK_ASSERT_CTX_VALID(ctx);
15617  DUK_ASSERT(key != NULL);
15618 
15619  obj_idx = duk_normalize_index(ctx, obj_idx);
15620  (void) duk_push_lstring(ctx, key, key_len);
15621  return duk__put_prop_shared(ctx, obj_idx, -1);
15622 }
15623 
15624 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
15625  DUK_ASSERT_CTX_VALID(ctx);
15626 
15627  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15628  duk_push_uarridx(ctx, arr_idx);
15629  return duk__put_prop_shared(ctx, obj_idx, -1);
15630 }
15631 
15632 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx) {
15633  duk_hthread *thr = (duk_hthread *) ctx;
15634 
15635  DUK_ASSERT_CTX_VALID(ctx);
15636  DUK_ASSERT_STRIDX_VALID(stridx);
15637  DUK_UNREF(thr);
15638 
15639  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15640  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
15641  return duk__put_prop_shared(ctx, obj_idx, -1);
15642 }
15643 
15644 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args) {
15645  return duk_put_prop_stridx(ctx, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
15646  (duk_small_uint_t) (packed_args & 0xffffUL));
15647 }
15648 
15649 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx) {
15650  duk_hthread *thr = (duk_hthread *) ctx;
15651  duk_tval *tv_obj;
15652  duk_tval *tv_key;
15653  duk_small_int_t throw_flag;
15654  duk_bool_t rc;
15655 
15656  DUK_ASSERT_CTX_VALID(ctx);
15657 
15658  /* Note: copying tv_obj and tv_key to locals to shield against a valstack
15659  * resize is not necessary for a property delete right now.
15660  */
15661 
15662  tv_obj = duk_require_tval(ctx, obj_idx);
15663  tv_key = duk_require_tval(ctx, -1);
15664  throw_flag = duk_is_strict_call(ctx);
15665 
15666  rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
15667  DUK_ASSERT(rc == 0 || rc == 1);
15668 
15669  duk_pop(ctx); /* remove key */
15670  return rc;
15671 }
15672 
15673 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
15674  DUK_ASSERT_CTX_VALID(ctx);
15675  DUK_ASSERT(key != NULL);
15676 
15677  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15678  duk_push_string(ctx, key);
15679  return duk_del_prop(ctx, obj_idx);
15680 }
15681 
15682 DUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
15683  DUK_ASSERT_CTX_VALID(ctx);
15684  DUK_ASSERT(key != NULL);
15685 
15686  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15687  duk_push_lstring(ctx, key, key_len);
15688  return duk_del_prop(ctx, obj_idx);
15689 }
15690 
15691 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
15692  DUK_ASSERT_CTX_VALID(ctx);
15693 
15694  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15695  duk_push_uarridx(ctx, arr_idx);
15696  return duk_del_prop(ctx, obj_idx);
15697 }
15698 
15699 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx) {
15700  duk_hthread *thr = (duk_hthread *) ctx;
15701 
15702  DUK_ASSERT_CTX_VALID(ctx);
15703  DUK_ASSERT_STRIDX_VALID(stridx);
15704  DUK_UNREF(thr);
15705 
15706  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15707  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
15708  return duk_del_prop(ctx, obj_idx);
15709 }
15710 
15711 #if 0
15712 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args) {
15713  return duk_del_prop_stridx(ctx, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
15714  (duk_small_uint_t) (packed_args & 0xffffUL));
15715 }
15716 #endif
15717 
15718 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx) {
15719  duk_hthread *thr = (duk_hthread *) ctx;
15720  duk_tval *tv_obj;
15721  duk_tval *tv_key;
15722  duk_bool_t rc;
15723 
15724  DUK_ASSERT_CTX_VALID(ctx);
15725 
15726  /* Note: copying tv_obj and tv_key to locals to shield against a valstack
15727  * resize is not necessary for a property existence check right now.
15728  */
15729 
15730  tv_obj = duk_require_tval(ctx, obj_idx);
15731  tv_key = duk_require_tval(ctx, -1);
15732 
15733  rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
15734  DUK_ASSERT(rc == 0 || rc == 1);
15735 
15736  duk_pop(ctx); /* remove key */
15737  return rc; /* 1 if property found, 0 otherwise */
15738 }
15739 
15740 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key) {
15741  DUK_ASSERT_CTX_VALID(ctx);
15742  DUK_ASSERT(key != NULL);
15743 
15744  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15745  duk_push_string(ctx, key);
15746  return duk_has_prop(ctx, obj_idx);
15747 }
15748 
15749 DUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {
15750  DUK_ASSERT_CTX_VALID(ctx);
15751  DUK_ASSERT(key != NULL);
15752 
15753  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15754  duk_push_lstring(ctx, key, key_len);
15755  return duk_has_prop(ctx, obj_idx);
15756 }
15757 
15758 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
15759  DUK_ASSERT_CTX_VALID(ctx);
15760 
15761  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15762  duk_push_uarridx(ctx, arr_idx);
15763  return duk_has_prop(ctx, obj_idx);
15764 }
15765 
15766 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx) {
15767  duk_hthread *thr = (duk_hthread *) ctx;
15768 
15769  DUK_ASSERT_CTX_VALID(ctx);
15770  DUK_ASSERT_STRIDX_VALID(stridx);
15771  DUK_UNREF(thr);
15772 
15773  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15774  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
15775  return duk_has_prop(ctx, obj_idx);
15776 }
15777 
15778 #if 0
15779 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args) {
15780  return duk_has_prop_stridx(ctx, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
15781  (duk_small_uint_t) (packed_args & 0xffffUL));
15782 }
15783 #endif
15784 
15785 /* Define own property without inheritance lookups and such. This differs from
15786  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
15787  * not invoked by this method. The caller must be careful to invoke any such
15788  * behaviors if necessary.
15789  */
15790 DUK_INTERNAL void duk_xdef_prop(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
15791  duk_hthread *thr = (duk_hthread *) ctx;
15792  duk_hobject *obj;
15793  duk_hstring *key;
15794 
15795  DUK_ASSERT_CTX_VALID(ctx);
15796 
15797  obj = duk_require_hobject(ctx, obj_idx);
15798  DUK_ASSERT(obj != NULL);
15799  key = duk_to_property_key_hstring(ctx, -2);
15800  DUK_ASSERT(key != NULL);
15801  DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
15802 
15803  duk_hobject_define_property_internal(thr, obj, key, desc_flags);
15804 
15805  duk_pop(ctx); /* pop key */
15806 }
15807 
15808 DUK_INTERNAL void duk_xdef_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags) {
15809  duk_hthread *thr = (duk_hthread *) ctx;
15810  duk_hobject *obj;
15811 
15812  DUK_ASSERT_CTX_VALID(ctx);
15813 
15814  obj = duk_require_hobject(ctx, obj_idx);
15815  DUK_ASSERT(obj != NULL);
15816 
15817  duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
15818  /* value popped by call */
15819 }
15820 
15821 DUK_INTERNAL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags) {
15822  duk_hthread *thr = (duk_hthread *) ctx;
15823  duk_hobject *obj;
15824  duk_hstring *key;
15825 
15826  DUK_ASSERT_CTX_VALID(ctx);
15827  DUK_ASSERT_STRIDX_VALID(stridx);
15828 
15829  obj = duk_require_hobject(ctx, obj_idx);
15830  DUK_ASSERT(obj != NULL);
15831  key = DUK_HTHREAD_GET_STRING(thr, stridx);
15832  DUK_ASSERT(key != NULL);
15833  DUK_ASSERT(duk_require_tval(ctx, -1) != NULL);
15834 
15835  duk_hobject_define_property_internal(thr, obj, key, desc_flags);
15836  /* value popped by call */
15837 }
15838 
15839 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_context *ctx, duk_uint_t packed_args) {
15840  duk_xdef_prop_stridx(ctx, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
15841  (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
15842  (duk_small_uint_t) (packed_args & 0xffL));
15843 }
15844 
15845 DUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {
15846  duk_hthread *thr = (duk_hthread *) ctx;
15847  duk_hobject *obj;
15848  duk_hstring *key;
15849 
15850  DUK_ASSERT_CTX_VALID(ctx);
15851  DUK_ASSERT_STRIDX_VALID(stridx);
15852  DUK_ASSERT_BIDX_VALID(builtin_idx);
15853 
15854  obj = duk_require_hobject(ctx, obj_idx);
15855  DUK_ASSERT(obj != NULL);
15856  key = DUK_HTHREAD_GET_STRING(thr, stridx);
15857  DUK_ASSERT(key != NULL);
15858 
15859  duk_push_hobject(ctx, thr->builtins[builtin_idx]);
15860  duk_hobject_define_property_internal(thr, obj, key, desc_flags);
15861  /* value popped by call */
15862 }
15863 
15864 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
15865  * setter/getter into an object property. This is needed by the 'arguments'
15866  * object creation code, function instance creation code, and Function.prototype.bind().
15867  */
15868 
15869 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_idx, duk_small_uint_t stridx) {
15870  obj_idx = duk_require_normalize_index(ctx, obj_idx);
15871  duk_push_hstring_stridx(ctx, stridx);
15872  duk_push_hobject_bidx(ctx, DUK_BIDX_TYPE_ERROR_THROWER);
15873  duk_dup_top(ctx);
15874  duk_def_prop(ctx, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE); /* attributes always 0 */
15875 }
15876 
15877 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
15878 DUK_EXTERNAL void duk_get_prop_desc(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags) {
15879  DUK_UNREF(flags); /* no flags defined yet */
15880 
15881  duk_hobject_object_get_own_property_descriptor(ctx, obj_idx); /* [ ... key ] -> [ ... desc ] */
15882 }
15883 
15884 /* Object.defineProperty() equivalent C binding. */
15885 DUK_EXTERNAL void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags) {
15886  duk_hthread *thr = (duk_hthread *) ctx;
15887  duk_idx_t idx_base;
15888  duk_hobject *obj;
15889  duk_hstring *key;
15890  duk_idx_t idx_value;
15891  duk_hobject *get;
15892  duk_hobject *set;
15893  duk_uint_t is_data_desc;
15894  duk_uint_t is_acc_desc;
15895 
15896  DUK_ASSERT_CTX_VALID(ctx);
15897 
15898  obj = duk_require_hobject(ctx, obj_idx);
15899 
15900  is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
15901  is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
15902  if (is_data_desc && is_acc_desc) {
15903  /* "Have" flags must not be conflicting so that they would
15904  * apply to both a plain property and an accessor at the same
15905  * time.
15906  */
15907  goto fail_invalid_desc;
15908  }
15909 
15910  idx_base = duk_get_top_index(ctx);
15911  if (flags & DUK_DEFPROP_HAVE_SETTER) {
15912  duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
15913  DUK_TYPE_MASK_OBJECT |
15914  DUK_TYPE_MASK_LIGHTFUNC);
15915  set = duk_get_hobject_promote_lfunc(ctx, idx_base);
15916  if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
15917  goto fail_not_callable;
15918  }
15919  idx_base--;
15920  } else {
15921  set = NULL;
15922  }
15923  if (flags & DUK_DEFPROP_HAVE_GETTER) {
15924  duk_require_type_mask(ctx, idx_base, DUK_TYPE_MASK_UNDEFINED |
15925  DUK_TYPE_MASK_OBJECT |
15926  DUK_TYPE_MASK_LIGHTFUNC);
15927  get = duk_get_hobject_promote_lfunc(ctx, idx_base);
15928  if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
15929  goto fail_not_callable;
15930  }
15931  idx_base--;
15932  } else {
15933  get = NULL;
15934  }
15935  if (flags & DUK_DEFPROP_HAVE_VALUE) {
15936  idx_value = idx_base;
15937  idx_base--;
15938  } else {
15939  idx_value = (duk_idx_t) -1;
15940  }
15941  key = duk_to_property_key_hstring(ctx, idx_base);
15942  DUK_ASSERT(key != NULL);
15943 
15944  duk_require_valid_index(ctx, idx_base);
15945 
15946  duk_hobject_define_property_helper(ctx,
15947  flags /*defprop_flags*/,
15948  obj,
15949  key,
15950  idx_value,
15951  get,
15952  set,
15953  1 /*throw_flag*/);
15954 
15955  /* Clean up stack */
15956 
15957  duk_set_top(ctx, idx_base);
15958 
15959  /* [ ... obj ... ] */
15960 
15961  return;
15962 
15963  fail_invalid_desc:
15964  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
15965  return;
15966 
15967  fail_not_callable:
15968  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
15969  return;
15970 }
15971 
15972 /*
15973  * Object related
15974  *
15975  * Note: seal() and freeze() are accessible through Ecmascript bindings,
15976  * and are not exposed through the API.
15977  */
15978 
15979 DUK_EXTERNAL void duk_compact(duk_context *ctx, duk_idx_t obj_idx) {
15980  duk_hthread *thr = (duk_hthread *) ctx;
15981  duk_hobject *obj;
15982 
15983  DUK_ASSERT_CTX_VALID(ctx);
15984 
15985  obj = duk_get_hobject(ctx, obj_idx);
15986  if (obj) {
15987  /* Note: this may fail, caller should protect the call if necessary */
15988  duk_hobject_compact_props(thr, obj);
15989  }
15990 }
15991 
15992 DUK_INTERNAL void duk_compact_m1(duk_context *ctx) {
15993  duk_compact(ctx, -1);
15994 }
15995 
15996 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
15997 
15998 DUK_EXTERNAL void duk_enum(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t enum_flags) {
15999  DUK_ASSERT_CTX_VALID(ctx);
16000 
16001  duk_dup(ctx, obj_idx);
16002  duk_require_hobject_promote_mask(ctx, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
16003  duk_hobject_enumerator_create(ctx, enum_flags); /* [target] -> [enum] */
16004 }
16005 
16006 DUK_EXTERNAL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_index, duk_bool_t get_value) {
16007  DUK_ASSERT_CTX_VALID(ctx);
16008 
16009  duk_require_hobject(ctx, enum_index);
16010  duk_dup(ctx, enum_index);
16011  return duk_hobject_enumerator_next(ctx, get_value);
16012 }
16013 
16014 /*
16015  * Helpers for writing multiple properties
16016  */
16017 
16018 DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
16019  const duk_function_list_entry *ent = funcs;
16020 
16021  DUK_ASSERT_CTX_VALID(ctx);
16022 
16023  obj_idx = duk_require_normalize_index(ctx, obj_idx);
16024  if (ent != NULL) {
16025  while (ent->key != NULL) {
16026  duk_push_c_function(ctx, ent->value, ent->nargs);
16027  duk_put_prop_string(ctx, obj_idx, ent->key);
16028  ent++;
16029  }
16030  }
16031 }
16032 
16033 DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
16034  const duk_number_list_entry *ent = numbers;
16035  duk_tval *tv;
16036 
16037  DUK_ASSERT_CTX_VALID(ctx);
16038 
16039  obj_idx = duk_require_normalize_index(ctx, obj_idx);
16040  if (ent != NULL) {
16041  while (ent->key != NULL) {
16042  tv = ((duk_hthread *) ctx)->valstack_top++;
16043  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv)); /* value stack init policy */
16044  DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value); /* no need for decref/incref */
16045  duk_put_prop_string(ctx, obj_idx, ent->key);
16046  ent++;
16047  }
16048  }
16049 }
16050 
16051 /*
16052  * Shortcut for accessing global object properties
16053  */
16054 
16055 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key) {
16056  duk_hthread *thr = (duk_hthread *) ctx;
16057  duk_bool_t ret;
16058 
16059  DUK_ASSERT_CTX_VALID(ctx);
16060  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
16061 
16062  /* XXX: direct implementation */
16063 
16064  duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
16065  ret = duk_get_prop_string(ctx, -1, key);
16066  duk_remove_m2(ctx);
16067  return ret;
16068 }
16069 
16070 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len) {
16071  duk_hthread *thr = (duk_hthread *) ctx;
16072  duk_bool_t ret;
16073 
16074  DUK_ASSERT_CTX_VALID(ctx);
16075  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
16076 
16077  /* XXX: direct implementation */
16078 
16079  duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
16080  ret = duk_get_prop_lstring(ctx, -1, key, key_len);
16081  duk_remove_m2(ctx);
16082  return ret;
16083 }
16084 
16085 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key) {
16086  duk_hthread *thr = (duk_hthread *) ctx;
16087  duk_bool_t ret;
16088 
16089  DUK_ASSERT_CTX_VALID(ctx);
16090  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
16091 
16092  /* XXX: direct implementation */
16093 
16094  duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
16095  duk_insert(ctx, -2);
16096  ret = duk_put_prop_string(ctx, -2, key); /* [ ... global val ] -> [ ... global ] */
16097  duk_pop(ctx);
16098  return ret;
16099 }
16100 
16101 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len) {
16102  duk_hthread *thr = (duk_hthread *) ctx;
16103  duk_bool_t ret;
16104 
16105  DUK_ASSERT_CTX_VALID(ctx);
16106  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
16107 
16108  /* XXX: direct implementation */
16109 
16110  duk_push_hobject(ctx, thr->builtins[DUK_BIDX_GLOBAL]);
16111  duk_insert(ctx, -2);
16112  ret = duk_put_prop_lstring(ctx, -2, key, key_len); /* [ ... global val ] -> [ ... global ] */
16113  duk_pop(ctx);
16114  return ret;
16115 }
16116 
16117 /*
16118  * Object prototype
16119  */
16120 
16121 DUK_EXTERNAL void duk_get_prototype(duk_context *ctx, duk_idx_t idx) {
16122  duk_hthread *thr = (duk_hthread *) ctx;
16123  duk_hobject *obj;
16124  duk_hobject *proto;
16125 
16126  DUK_ASSERT_CTX_VALID(ctx);
16127  DUK_UNREF(thr);
16128 
16129  obj = duk_require_hobject(ctx, idx);
16130  DUK_ASSERT(obj != NULL);
16131 
16132  /* XXX: shared helper for duk_push_hobject_or_undefined()? */
16133  proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
16134  if (proto) {
16135  duk_push_hobject(ctx, proto);
16136  } else {
16137  duk_push_undefined(ctx);
16138  }
16139 }
16140 
16141 DUK_EXTERNAL void duk_set_prototype(duk_context *ctx, duk_idx_t idx) {
16142  duk_hthread *thr = (duk_hthread *) ctx;
16143  duk_hobject *obj;
16144  duk_hobject *proto;
16145 
16146  DUK_ASSERT_CTX_VALID(ctx);
16147 
16148  obj = duk_require_hobject(ctx, idx);
16149  DUK_ASSERT(obj != NULL);
16150  duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_UNDEFINED |
16151  DUK_TYPE_MASK_OBJECT);
16152  proto = duk_get_hobject(ctx, -1);
16153  /* proto can also be NULL here (allowed explicitly) */
16154 
16155 #if defined(DUK_USE_ROM_OBJECTS)
16156  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
16157  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE); /* XXX: "read only object"? */
16158  return;
16159  }
16160 #endif
16161 
16162  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
16163 
16164  duk_pop(ctx);
16165 }
16166 
16167 /*
16168  * Object finalizer
16169  */
16170 
16171 #if defined(DUK_USE_FINALIZER_SUPPORT)
16172 /* XXX: these could be implemented as macros calling an internal function
16173  * directly.
16174  * XXX: same issue as with Duktape.fin: there's no way to delete the property
16175  * now (just set it to undefined).
16176  */
16177 DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t idx) {
16178  DUK_ASSERT_CTX_VALID(ctx);
16179 
16180  duk_get_prop_stridx(ctx, idx, DUK_STRIDX_INT_FINALIZER);
16181 }
16182 
16183 DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t idx) {
16184  DUK_ASSERT_CTX_VALID(ctx);
16185 
16186  duk_put_prop_stridx(ctx, idx, DUK_STRIDX_INT_FINALIZER);
16187 }
16188 #else /* DUK_USE_FINALIZER_SUPPORT */
16189 DUK_EXTERNAL void duk_get_finalizer(duk_context *ctx, duk_idx_t idx) {
16190  DUK_ASSERT_CTX_VALID(ctx);
16191  DUK_UNREF(idx);
16192  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
16193 }
16194 
16195 DUK_EXTERNAL void duk_set_finalizer(duk_context *ctx, duk_idx_t idx) {
16196  DUK_ASSERT_CTX_VALID(ctx);
16197  DUK_UNREF(idx);
16198  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
16199 }
16200 #endif /* DUK_USE_FINALIZER_SUPPORT */
16201 /*
16202  * API calls related to general value stack manipulation: resizing the value
16203  * stack, pushing and popping values, type checking and reading values,
16204  * coercing values, etc.
16205  *
16206  * Also contains internal functions (such as duk_get_tval()), defined
16207  * in duk_api_internal.h, with semantics similar to the public API.
16208  */
16209 
16210 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
16211 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
16212 
16213 /* #include duk_internal.h -> already included */
16214 
16215 /*
16216  * Forward declarations
16217  */
16218 
16219 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);
16220 
16221 /*
16222  * Global state for working around missing variadic macros
16223  */
16224 
16225 #if !defined(DUK_USE_VARIADIC_MACROS)
16226 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
16227 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
16228 #endif
16229 
16230 /*
16231  * Misc helpers
16232  */
16233 
16234 #if !defined(DUK_USE_PACKED_TVAL)
16235 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
16236  DUK_TYPE_NUMBER,
16237  DUK_TYPE_NUMBER, /* fastint */
16238  DUK_TYPE_UNDEFINED,
16239  DUK_TYPE_NULL,
16240  DUK_TYPE_BOOLEAN,
16241  DUK_TYPE_POINTER,
16242  DUK_TYPE_LIGHTFUNC,
16243  DUK_TYPE_NONE,
16244  DUK_TYPE_STRING,
16245  DUK_TYPE_OBJECT,
16246  DUK_TYPE_BUFFER,
16247 };
16248 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
16249  DUK_TYPE_MASK_NUMBER,
16250  DUK_TYPE_MASK_NUMBER, /* fastint */
16251  DUK_TYPE_MASK_UNDEFINED,
16252  DUK_TYPE_MASK_NULL,
16253  DUK_TYPE_MASK_BOOLEAN,
16254  DUK_TYPE_MASK_POINTER,
16255  DUK_TYPE_MASK_LIGHTFUNC,
16256  DUK_TYPE_MASK_NONE,
16257  DUK_TYPE_MASK_STRING,
16258  DUK_TYPE_MASK_OBJECT,
16259  DUK_TYPE_MASK_BUFFER,
16260 };
16261 #endif /* !DUK_USE_PACKED_TVAL */
16262 
16263 /* Check that there's room to push one value. */
16264 #if defined(DUK_USE_VALSTACK_UNSAFE)
16265 /* Faster but value stack overruns are memory unsafe. */
16266 #define DUK__CHECK_SPACE() do { \
16267  DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
16268  } while (0)
16269 #else
16270 #define DUK__CHECK_SPACE() do { \
16271  if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
16272  DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
16273  } \
16274  } while (0)
16275 #endif
16276 
16277 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t idx, duk_uint_t tag);
16278 
16279 DUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_context *ctx, duk_idx_t idx, duk_bool_t require) {
16280  duk_hthread *thr;
16281  duk_tval *tv;
16282  duk_small_int_t c;
16283  duk_double_t d;
16284 
16285  thr = (duk_hthread *) ctx;
16286 
16287  tv = duk_get_tval_or_unused(ctx, idx);
16288  DUK_ASSERT(tv != NULL);
16289 
16290  /*
16291  * Special cases like NaN and +/- Infinity are handled explicitly
16292  * because a plain C coercion from double to int handles these cases
16293  * in undesirable ways. For instance, NaN may coerce to INT_MIN
16294  * (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
16295  *
16296  * This double-to-int coercion differs from ToInteger() because it
16297  * has a finite range (ToInteger() allows e.g. +/- Infinity). It
16298  * also differs from ToInt32() because the INT_MIN/INT_MAX clamping
16299  * depends on the size of the int type on the platform. In particular,
16300  * on platforms with a 64-bit int type, the full range is allowed.
16301  */
16302 
16303 #if defined(DUK_USE_FASTINT)
16304  if (DUK_TVAL_IS_FASTINT(tv)) {
16305  duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
16306 #if (DUK_INT_MAX <= 0x7fffffffL)
16307  /* Clamping only necessary for 32-bit ints. */
16308  if (t < DUK_INT_MIN) {
16309  t = DUK_INT_MIN;
16310  } else if (t > DUK_INT_MAX) {
16311  t = DUK_INT_MAX;
16312  }
16313 #endif
16314  return (duk_int_t) t;
16315  }
16316 #endif
16317 
16318  if (DUK_TVAL_IS_NUMBER(tv)) {
16319  d = DUK_TVAL_GET_NUMBER(tv);
16320  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
16321  if (c == DUK_FP_NAN) {
16322  return 0;
16323  } else if (d < (duk_double_t) DUK_INT_MIN) {
16324  /* covers -Infinity */
16325  return DUK_INT_MIN;
16326  } else if (d > (duk_double_t) DUK_INT_MAX) {
16327  /* covers +Infinity */
16328  return DUK_INT_MAX;
16329  } else {
16330  /* coerce towards zero */
16331  return (duk_int_t) d;
16332  }
16333  }
16334 
16335  if (require) {
16336  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
16337  /* not reachable */
16338  }
16339  return 0;
16340 }
16341 
16342 DUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_context *ctx, duk_idx_t idx, duk_bool_t require) {
16343  duk_hthread *thr;
16344  duk_tval *tv;
16345  duk_small_int_t c;
16346  duk_double_t d;
16347 
16348  /* Same as above but for unsigned int range. */
16349 
16350  thr = (duk_hthread *) ctx;
16351 
16352  tv = duk_get_tval_or_unused(ctx, idx);
16353  DUK_ASSERT(tv != NULL);
16354 
16355 #if defined(DUK_USE_FASTINT)
16356  if (DUK_TVAL_IS_FASTINT(tv)) {
16357  duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
16358  if (t < 0) {
16359  t = 0;
16360  }
16361 #if (DUK_UINT_MAX <= 0xffffffffUL)
16362  /* Clamping only necessary for 32-bit ints. */
16363  else if (t > DUK_UINT_MAX) {
16364  t = DUK_UINT_MAX;
16365  }
16366 #endif
16367  return (duk_uint_t) t;
16368  }
16369 #endif
16370 
16371  if (DUK_TVAL_IS_NUMBER(tv)) {
16372  d = DUK_TVAL_GET_NUMBER(tv);
16373  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
16374  if (c == DUK_FP_NAN) {
16375  return 0;
16376  } else if (d < 0.0) {
16377  /* covers -Infinity */
16378  return (duk_uint_t) 0;
16379  } else if (d > (duk_double_t) DUK_UINT_MAX) {
16380  /* covers +Infinity */
16381  return (duk_uint_t) DUK_UINT_MAX;
16382  } else {
16383  /* coerce towards zero */
16384  return (duk_uint_t) d;
16385  }
16386  }
16387 
16388  if (require) {
16389  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
16390  /* not reachable */
16391  }
16392  return 0;
16393 }
16394 
16395 /*
16396  * Stack index validation/normalization and getting a stack duk_tval ptr.
16397  *
16398  * These are called by many API entrypoints so the implementations must be
16399  * fast and "inlined".
16400  *
16401  * There's some repetition because of this; keep the functions in sync.
16402  */
16403 
16404 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t idx) {
16405  duk_hthread *thr = (duk_hthread *) ctx;
16406  duk_uidx_t vs_size;
16407  duk_uidx_t uidx;
16408 
16409  DUK_ASSERT_CTX_VALID(ctx);
16410  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16411 
16412  /* Care must be taken to avoid pointer wrapping in the index
16413  * validation. For instance, on a 32-bit platform with 8-byte
16414  * duk_tval the index 0x20000000UL would wrap the memory space
16415  * once.
16416  */
16417 
16418  /* Assume value stack sizes (in elements) fits into duk_idx_t. */
16419  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16420  vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
16421  DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
16422 
16423  if (idx < 0) {
16424  uidx = vs_size + (duk_uidx_t) idx;
16425  } else {
16426  /* since index non-negative */
16427  DUK_ASSERT(idx != DUK_INVALID_INDEX);
16428  uidx = (duk_uidx_t) idx;
16429  }
16430 
16431  /* DUK_INVALID_INDEX won't be accepted as a valid index. */
16432  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
16433 
16434  if (DUK_LIKELY(uidx < vs_size)) {
16435  return (duk_idx_t) uidx;
16436  }
16437  return DUK_INVALID_INDEX;
16438 }
16439 
16440 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t idx) {
16441  duk_hthread *thr = (duk_hthread *) ctx;
16442  duk_uidx_t vs_size;
16443  duk_uidx_t uidx;
16444 
16445  DUK_ASSERT_CTX_VALID(ctx);
16446  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16447 
16448  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16449  vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
16450  DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
16451 
16452  if (idx < 0) {
16453  uidx = vs_size + (duk_uidx_t) idx;
16454  } else {
16455  DUK_ASSERT(idx != DUK_INVALID_INDEX);
16456  uidx = (duk_uidx_t) idx;
16457  }
16458 
16459  /* DUK_INVALID_INDEX won't be accepted as a valid index. */
16460  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
16461 
16462  if (DUK_LIKELY(uidx < vs_size)) {
16463  return (duk_idx_t) uidx;
16464  }
16465  DUK_ERROR_RANGE_INDEX(thr, idx);
16466  return 0; /* unreachable */
16467 }
16468 
16469 DUK_INTERNAL duk_tval *duk_get_tval(duk_context *ctx, duk_idx_t idx) {
16470  duk_hthread *thr = (duk_hthread *) ctx;
16471  duk_uidx_t vs_size;
16472  duk_uidx_t uidx;
16473 
16474  DUK_ASSERT_CTX_VALID(ctx);
16475  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16476 
16477  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16478  vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
16479  DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
16480 
16481  if (idx < 0) {
16482  uidx = vs_size + (duk_uidx_t) idx;
16483  } else {
16484  DUK_ASSERT(idx != DUK_INVALID_INDEX);
16485  uidx = (duk_uidx_t) idx;
16486  }
16487 
16488  /* DUK_INVALID_INDEX won't be accepted as a valid index. */
16489  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
16490 
16491  if (DUK_LIKELY(uidx < vs_size)) {
16492  return thr->valstack_bottom + uidx;
16493  }
16494  return NULL;
16495 }
16496 
16497 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
16498  * pointer. When duk_get_tval() would return NULL, this variant returns a
16499  * pointer to a duk_tval with tag DUK_TAG_UNUSED. This allows the call site
16500  * to avoid an unnecessary NULL check which sometimes leads to better code.
16501  * The return duk_tval is read only (at least for the UNUSED value).
16502  */
16503 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
16504 
16505 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_context *ctx, duk_idx_t idx) {
16506  duk_tval *tv;
16507  tv = duk_get_tval(ctx, idx);
16508  if (tv != NULL) {
16509  return tv;
16510  }
16511  return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
16512 }
16513 
16514 DUK_INTERNAL duk_tval *duk_require_tval(duk_context *ctx, duk_idx_t idx) {
16515  duk_hthread *thr = (duk_hthread *) ctx;
16516  duk_uidx_t vs_size;
16517  duk_uidx_t uidx;
16518 
16519  DUK_ASSERT_CTX_VALID(ctx);
16520  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16521 
16522  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16523  vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
16524  DUK_ASSERT_DISABLE(vs_size >= 0); /* unsigned */
16525 
16526  /* Use unsigned arithmetic to optimize comparison. */
16527  if (idx < 0) {
16528  uidx = vs_size + (duk_uidx_t) idx;
16529  } else {
16530  DUK_ASSERT(idx != DUK_INVALID_INDEX);
16531  uidx = (duk_uidx_t) idx;
16532  }
16533 
16534  /* DUK_INVALID_INDEX won't be accepted as a valid index. */
16535  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
16536 
16537  if (DUK_LIKELY(uidx < vs_size)) {
16538  return thr->valstack_bottom + uidx;
16539  }
16540  DUK_ERROR_RANGE_INDEX(thr, idx);
16541  return NULL;
16542 }
16543 
16544 /* Non-critical. */
16545 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t idx) {
16546  DUK_ASSERT_CTX_VALID(ctx);
16547  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16548 
16549  return (duk_normalize_index(ctx, idx) >= 0);
16550 }
16551 
16552 /* Non-critical. */
16553 DUK_EXTERNAL void duk_require_valid_index(duk_context *ctx, duk_idx_t idx) {
16554  duk_hthread *thr = (duk_hthread *) ctx;
16555 
16556  DUK_ASSERT_CTX_VALID(ctx);
16557  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16558 
16559  if (duk_normalize_index(ctx, idx) < 0) {
16560  DUK_ERROR_RANGE_INDEX(thr, idx);
16561  return; /* unreachable */
16562  }
16563 }
16564 
16565 /*
16566  * Value stack top handling
16567  */
16568 
16569 DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) {
16570  duk_hthread *thr = (duk_hthread *) ctx;
16571 
16572  DUK_ASSERT_CTX_VALID(ctx);
16573 
16574  return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
16575 }
16576 
16577 /* Internal helper to get current top but to require a minimum top value
16578  * (TypeError if not met).
16579  */
16580 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_context *ctx, duk_idx_t min_top) {
16581  duk_hthread *thr = (duk_hthread *) ctx;
16582  duk_idx_t ret;
16583 
16584  DUK_ASSERT_CTX_VALID(ctx);
16585 
16586  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
16587  if (ret < min_top) {
16588  DUK_ERROR_TYPE_INVALID_ARGS(thr);
16589  }
16590  return ret;
16591 }
16592 
16593 /* Set stack top within currently allocated range, but don't reallocate.
16594  * This is performance critical especially for call handling, so whenever
16595  * changing, profile and look at generated code.
16596  */
16597 DUK_EXTERNAL void duk_set_top(duk_context *ctx, duk_idx_t idx) {
16598  duk_hthread *thr = (duk_hthread *) ctx;
16599  duk_uidx_t vs_size;
16600  duk_uidx_t vs_limit;
16601  duk_uidx_t uidx;
16602  duk_tval *tv;
16603 
16604  DUK_ASSERT_CTX_VALID(ctx);
16605  DUK_ASSERT(DUK_INVALID_INDEX < 0);
16606 
16607  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16608  DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
16609  vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
16610  vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
16611 
16612  if (idx < 0) {
16613  /* Negative indices are always within allocated stack but
16614  * must not go below zero index.
16615  */
16616  uidx = vs_size + (duk_uidx_t) idx;
16617  } else {
16618  /* Positive index can be higher than valstack top but must
16619  * not go above allocated stack (equality is OK).
16620  */
16621  uidx = (duk_uidx_t) idx;
16622  }
16623 
16624  /* DUK_INVALID_INDEX won't be accepted as a valid index. */
16625  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
16626  DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
16627 
16628 #if defined(DUK_USE_VALSTACK_UNSAFE)
16629  DUK_ASSERT(uidx <= vs_limit);
16630  DUK_UNREF(vs_limit);
16631 #else
16632  if (DUK_UNLIKELY(uidx > vs_limit)) {
16633  DUK_ERROR_RANGE_INDEX(thr, idx);
16634  return; /* unreachable */
16635  }
16636 #endif
16637  DUK_ASSERT(uidx <= vs_limit);
16638 
16639  /* Handle change in value stack top. Respect value stack
16640  * initialization policy: 'undefined' above top. Note that
16641  * DECREF may cause a side effect that reallocates valstack,
16642  * so must relookup after DECREF.
16643  */
16644 
16645  if (uidx >= vs_size) {
16646  /* Stack size increases or stays the same. */
16647 #if defined(DUK_USE_ASSERTIONS)
16648  duk_uidx_t count;
16649 
16650  count = uidx - vs_size;
16651  while (count != 0) {
16652  count--;
16653  tv = thr->valstack_top + count;
16654  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
16655  }
16656 #endif
16657  thr->valstack_top = thr->valstack_bottom + uidx;
16658  } else {
16659  /* Stack size decreases. */
16660 #if defined(DUK_USE_REFERENCE_COUNTING)
16661  duk_uidx_t count;
16662  duk_tval *tv_end;
16663 
16664  count = vs_size - uidx;
16665  DUK_ASSERT(count > 0);
16666  tv = thr->valstack_top;
16667  tv_end = tv - count;
16668  DUK_ASSERT(tv > tv_end); /* Because count > 0. */
16669  do {
16670  tv--;
16671  DUK_ASSERT(tv >= thr->valstack_bottom);
16672  DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
16673  } while (tv != tv_end);
16674  thr->valstack_top = tv_end;
16675  DUK_REFZERO_CHECK_FAST(thr);
16676 #else /* DUK_USE_REFERENCE_COUNTING */
16677  duk_uidx_t count;
16678  duk_tval *tv_end;
16679 
16680  count = vs_size - uidx;
16681  tv = thr->valstack_top;
16682  tv_end = tv - count;
16683  DUK_ASSERT(tv > tv_end);
16684  do {
16685  tv--;
16686  DUK_TVAL_SET_UNDEFINED(tv);
16687  } while (tv != tv_end);
16688  thr->valstack_top = tv_end;
16689 #endif /* DUK_USE_REFERENCE_COUNTING */
16690  }
16691 }
16692 
16693 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_context *ctx) {
16694  duk_hthread *thr = (duk_hthread *) ctx;
16695  duk_idx_t ret;
16696 
16697  DUK_ASSERT_CTX_VALID(ctx);
16698 
16699  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
16700  if (DUK_UNLIKELY(ret < 0)) {
16701  /* Return invalid index; if caller uses this without checking
16702  * in another API call, the index won't map to a valid stack
16703  * entry.
16704  */
16705  return DUK_INVALID_INDEX;
16706  }
16707  return ret;
16708 }
16709 
16710 /* Internal variant: call assumes there is at least one element on the value
16711  * stack frame; this is only asserted for.
16712  */
16713 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_context *ctx) {
16714  duk_hthread *thr = (duk_hthread *) ctx;
16715  duk_idx_t ret;
16716 
16717  DUK_ASSERT_CTX_VALID(ctx);
16718 
16719  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
16720  return ret;
16721 }
16722 
16723 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_context *ctx) {
16724  duk_hthread *thr = (duk_hthread *) ctx;
16725  duk_idx_t ret;
16726 
16727  DUK_ASSERT_CTX_VALID(ctx);
16728 
16729  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
16730  if (DUK_UNLIKELY(ret < 0)) {
16731  DUK_ERROR_RANGE_INDEX(thr, -1);
16732  return 0; /* unreachable */
16733  }
16734  return ret;
16735 }
16736 
16737 /*
16738  * Value stack resizing.
16739  *
16740  * This resizing happens above the current "top": the value stack can be
16741  * grown or shrunk, but the "top" is not affected. The value stack cannot
16742  * be resized to a size below the current "top".
16743  *
16744  * The low level reallocation primitive must carefully recompute all value
16745  * stack pointers, and must also work if ALL pointers are NULL. The resize
16746  * is quite tricky because the valstack realloc may cause a mark-and-sweep,
16747  * which may run finalizers. Running finalizers may resize the valstack
16748  * recursively (the same value stack we're working on). So, after realloc
16749  * returns, we know that the valstack "top" should still be the same (there
16750  * should not be live values above the "top"), but its underlying size and
16751  * pointer may have changed.
16752  */
16753 
16754 /* XXX: perhaps refactor this to allow caller to specify some parameters, or
16755  * at least a 'compact' flag which skips any spare or round-up .. useful for
16756  * emergency gc.
16757  */
16758 
16759 DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size) {
16760  duk_hthread *thr = (duk_hthread *) ctx;
16761  duk_ptrdiff_t old_bottom_offset;
16762  duk_ptrdiff_t old_top_offset;
16763  duk_ptrdiff_t old_end_offset_post;
16764 #if defined(DUK_USE_DEBUG)
16765  duk_ptrdiff_t old_end_offset_pre;
16766  duk_tval *old_valstack_pre;
16767  duk_tval *old_valstack_post;
16768 #endif
16769  duk_tval *new_valstack;
16770  duk_size_t new_alloc_size;
16771  duk_tval *p;
16772 
16773  DUK_ASSERT_CTX_VALID(ctx);
16774  DUK_ASSERT(thr != NULL);
16775  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
16776  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16777  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
16778  DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size); /* can't resize below 'top' */
16779  DUK_ASSERT(new_size <= thr->valstack_max); /* valstack limit caller has check, prevents wrapping */
16780  DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval)); /* specific assert for wrapping */
16781 
16782  /* get pointer offsets for tweaking below */
16783  old_bottom_offset = (((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack));
16784  old_top_offset = (((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack));
16785 #if defined(DUK_USE_DEBUG)
16786  old_end_offset_pre = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* not very useful, used for debugging */
16787  old_valstack_pre = thr->valstack;
16788 #endif
16789 
16790  /* Allocate a new valstack.
16791  *
16792  * Note: cannot use a plain DUK_REALLOC() because a mark-and-sweep may
16793  * invalidate the original thr->valstack base pointer inside the realloc
16794  * process. See doc/memory-management.rst.
16795  */
16796 
16797  new_alloc_size = sizeof(duk_tval) * new_size;
16798  new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
16799  if (!new_valstack) {
16800  /* Because new_size != 0, if condition doesn't need to be
16801  * (new_valstack != NULL || new_size == 0).
16802  */
16803  DUK_ASSERT(new_size != 0);
16804  DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
16805  (unsigned long) new_size, (unsigned long) new_alloc_size));
16806  return 0;
16807  }
16808 
16809  /* Note: the realloc may have triggered a mark-and-sweep which may
16810  * have resized our valstack internally. However, the mark-and-sweep
16811  * MUST NOT leave the stack bottom/top in a different state. Particular
16812  * assumptions and facts:
16813  *
16814  * - The thr->valstack pointer may be different after realloc,
16815  * and the offset between thr->valstack_end <-> thr->valstack
16816  * may have changed.
16817  * - The offset between thr->valstack_bottom <-> thr->valstack
16818  * and thr->valstack_top <-> thr->valstack MUST NOT have changed,
16819  * because mark-and-sweep must adhere to a strict stack policy.
16820  * In other words, logical bottom and top MUST NOT have changed.
16821  * - All values above the top are unreachable but are initialized
16822  * to UNDEFINED, up to the post-realloc valstack_end.
16823  * - 'old_end_offset' must be computed after realloc to be correct.
16824  */
16825 
16826  DUK_ASSERT((((duk_uint8_t *) thr->valstack_bottom) - ((duk_uint8_t *) thr->valstack)) == old_bottom_offset);
16827  DUK_ASSERT((((duk_uint8_t *) thr->valstack_top) - ((duk_uint8_t *) thr->valstack)) == old_top_offset);
16828 
16829  /* success, fixup pointers */
16830  old_end_offset_post = (((duk_uint8_t *) thr->valstack_end) - ((duk_uint8_t *) thr->valstack)); /* must be computed after realloc */
16831 #if defined(DUK_USE_DEBUG)
16832  old_valstack_post = thr->valstack;
16833 #endif
16834  thr->valstack = new_valstack;
16835  thr->valstack_end = new_valstack + new_size;
16836 #if !defined(DUK_USE_PREFER_SIZE)
16837  thr->valstack_size = new_size;
16838 #endif
16839  thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_bottom_offset);
16840  thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + old_top_offset);
16841 
16842  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
16843  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16844  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
16845 
16846  /* useful for debugging */
16847 #if defined(DUK_USE_DEBUG)
16848  if (old_end_offset_pre != old_end_offset_post) {
16849  DUK_D(DUK_DPRINT("valstack was resized during valstack_resize(), probably by mark-and-sweep; "
16850  "end offset changed: %lu -> %lu",
16851  (unsigned long) old_end_offset_pre,
16852  (unsigned long) old_end_offset_post));
16853  }
16854  if (old_valstack_pre != old_valstack_post) {
16855  DUK_D(DUK_DPRINT("valstack pointer changed during valstack_resize(), probably by mark-and-sweep: %p -> %p",
16856  (void *) old_valstack_pre,
16857  (void *) old_valstack_post));
16858  }
16859 #endif
16860 
16861  DUK_DD(DUK_DDPRINT("resized valstack to %lu elements (%lu bytes), bottom=%ld, top=%ld, "
16862  "new pointers: start=%p end=%p bottom=%p top=%p",
16863  (unsigned long) new_size, (unsigned long) new_alloc_size,
16864  (long) (thr->valstack_bottom - thr->valstack),
16865  (long) (thr->valstack_top - thr->valstack),
16866  (void *) thr->valstack, (void *) thr->valstack_end,
16867  (void *) thr->valstack_bottom, (void *) thr->valstack_top));
16868 
16869  /* Init newly allocated slots (only). */
16870  p = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + old_end_offset_post);
16871  while (p < thr->valstack_end) {
16872  /* Never executed if new size is smaller. */
16873  DUK_TVAL_SET_UNDEFINED(p);
16874  p++;
16875  }
16876 
16877  /* Assert for value stack initialization policy. */
16878 #if defined(DUK_USE_ASSERTIONS)
16879  p = thr->valstack_top;
16880  while (p < thr->valstack_end) {
16881  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
16882  p++;
16883  }
16884 #endif
16885 
16886  return 1;
16887 }
16888 
16889 DUK_INTERNAL
16890 duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
16891  duk_size_t min_new_size,
16892  duk_small_uint_t flags) {
16893  duk_hthread *thr = (duk_hthread *) ctx;
16894  duk_size_t old_size;
16895  duk_size_t new_size;
16896  duk_bool_t is_shrink = 0;
16897  duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
16898  duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
16899  duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
16900 
16901  DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
16902  "curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
16903  (unsigned long) min_new_size,
16904  (long) (thr->valstack_end - thr->valstack),
16905  (long) (thr->valstack_top - thr->valstack),
16906  (long) (thr->valstack_bottom - thr->valstack),
16907  (int) shrink_flag, (int) compact_flag, (int) throw_flag));
16908 
16909  DUK_ASSERT_CTX_VALID(ctx);
16910  DUK_ASSERT(thr != NULL);
16911  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
16912  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
16913  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
16914 
16915 #if defined(DUK_USE_PREFER_SIZE)
16916  old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
16917 #else
16918  DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
16919  old_size = thr->valstack_size;
16920 #endif
16921 
16922  if (min_new_size <= old_size) {
16923  is_shrink = 1;
16924  if (!shrink_flag ||
16925  old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) {
16926  DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
16927  return 1;
16928  }
16929  }
16930 
16931  new_size = min_new_size;
16932  if (!compact_flag) {
16933  if (is_shrink) {
16934  /* shrink case; leave some spare */
16935  new_size += DUK_VALSTACK_SHRINK_SPARE;
16936  }
16937 
16938  /* round up roughly to next 'grow step' */
16939  new_size = (new_size / DUK_VALSTACK_GROW_STEP + 1) * DUK_VALSTACK_GROW_STEP;
16940  }
16941 
16942  DUK_DD(DUK_DDPRINT("want to %s valstack: %lu -> %lu elements (min_new_size %lu)",
16943  (const char *) (new_size > old_size ? "grow" : "shrink"),
16944  (unsigned long) old_size, (unsigned long) new_size,
16945  (unsigned long) min_new_size));
16946 
16947  if (new_size > thr->valstack_max) {
16948  /* Note: may be triggered even if minimal new_size would not reach the limit,
16949  * plan limit accordingly (taking DUK_VALSTACK_GROW_STEP into account).
16950  */
16951  if (throw_flag) {
16952  DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
16953  } else {
16954  return 0;
16955  }
16956  }
16957 
16958  /*
16959  * When resizing the valstack, a mark-and-sweep may be triggered for
16960  * the allocation of the new valstack. If the mark-and-sweep needs
16961  * to use our thread for something, it may cause *the same valstack*
16962  * to be resized recursively. This happens e.g. when mark-and-sweep
16963  * finalizers are called. This is taken into account carefully in
16964  * duk__resize_valstack().
16965  *
16966  * 'new_size' is known to be <= valstack_max, which ensures that
16967  * size_t and pointer arithmetic won't wrap in duk__resize_valstack().
16968  */
16969 
16970  if (!duk__resize_valstack(ctx, new_size)) {
16971  if (is_shrink) {
16972  DUK_DD(DUK_DDPRINT("valstack resize failed, but is a shrink, ignore"));
16973  return 1;
16974  }
16975 
16976  DUK_DD(DUK_DDPRINT("valstack resize failed"));
16977 
16978  if (throw_flag) {
16979  DUK_ERROR_ALLOC_FAILED(thr);
16980  } else {
16981  return 0;
16982  }
16983  }
16984 
16985  DUK_DDD(DUK_DDDPRINT("valstack resize successful"));
16986  return 1;
16987 }
16988 
16989 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
16990  duk_hthread *thr = (duk_hthread *) ctx;
16991  duk_size_t min_new_size;
16992 
16993  DUK_ASSERT_CTX_VALID(ctx);
16994  DUK_ASSERT(thr != NULL);
16995 
16996  if (DUK_UNLIKELY(extra < 0)) {
16997  /* Clamping to zero makes the API more robust to calling code
16998  * calculation errors.
16999  */
17000  extra = 0;
17001  }
17002 
17003  min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
17004  return duk_valstack_resize_raw(ctx,
17005  min_new_size, /* min_new_size */
17006  0 /* no shrink */ | /* flags */
17007  0 /* no compact */ |
17008  0 /* no throw */);
17009 }
17010 
17011 DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra) {
17012  duk_hthread *thr = (duk_hthread *) ctx;
17013  duk_size_t min_new_size;
17014 
17015  DUK_ASSERT_CTX_VALID(ctx);
17016  DUK_ASSERT(thr != NULL);
17017 
17018  if (DUK_UNLIKELY(extra < 0)) {
17019  /* Clamping to zero makes the API more robust to calling code
17020  * calculation errors.
17021  */
17022  extra = 0;
17023  }
17024 
17025  min_new_size = (thr->valstack_top - thr->valstack) + extra + DUK_VALSTACK_INTERNAL_EXTRA;
17026  (void) duk_valstack_resize_raw(ctx,
17027  min_new_size, /* min_new_size */
17028  0 /* no shrink */ | /* flags */
17029  0 /* no compact */ |
17030  DUK_VSRESIZE_FLAG_THROW);
17031 }
17032 
17033 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top) {
17034  duk_size_t min_new_size;
17035 
17036  DUK_ASSERT_CTX_VALID(ctx);
17037 
17038  if (DUK_UNLIKELY(top < 0)) {
17039  /* Clamping to zero makes the API more robust to calling code
17040  * calculation errors.
17041  */
17042  top = 0;
17043  }
17044 
17045  min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
17046  return duk_valstack_resize_raw(ctx,
17047  min_new_size, /* min_new_size */
17048  0 /* no shrink */ | /* flags */
17049  0 /* no compact */ |
17050  0 /* no throw */);
17051 }
17052 
17053 DUK_EXTERNAL void duk_require_stack_top(duk_context *ctx, duk_idx_t top) {
17054  duk_size_t min_new_size;
17055 
17056  DUK_ASSERT_CTX_VALID(ctx);
17057 
17058  if (DUK_UNLIKELY(top < 0)) {
17059  /* Clamping to zero makes the API more robust to calling code
17060  * calculation errors.
17061  */
17062  top = 0;
17063  }
17064 
17065  min_new_size = top + DUK_VALSTACK_INTERNAL_EXTRA;
17066  (void) duk_valstack_resize_raw(ctx,
17067  min_new_size, /* min_new_size */
17068  0 /* no shrink */ | /* flags */
17069  0 /* no compact */ |
17070  DUK_VSRESIZE_FLAG_THROW);
17071 }
17072 
17073 /*
17074  * Basic stack manipulation: swap, dup, insert, replace, etc
17075  */
17076 
17077 DUK_EXTERNAL void duk_swap(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2) {
17078  duk_tval *tv1;
17079  duk_tval *tv2;
17080  duk_tval tv_tmp;
17081 
17082  DUK_ASSERT_CTX_VALID(ctx);
17083 
17084  tv1 = duk_require_tval(ctx, idx1);
17085  DUK_ASSERT(tv1 != NULL);
17086  tv2 = duk_require_tval(ctx, idx2);
17087  DUK_ASSERT(tv2 != NULL);
17088 
17089  /* If tv1==tv2 this is a NOP, no check is needed */
17090  DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
17091  DUK_TVAL_SET_TVAL(tv1, tv2);
17092  DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
17093 }
17094 
17095 DUK_EXTERNAL void duk_swap_top(duk_context *ctx, duk_idx_t idx) {
17096  DUK_ASSERT_CTX_VALID(ctx);
17097 
17098  duk_swap(ctx, idx, -1);
17099 }
17100 
17101 DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_idx) {
17102  duk_hthread *thr;
17103  duk_tval *tv_from;
17104  duk_tval *tv_to;
17105 
17106  DUK_ASSERT_CTX_VALID(ctx);
17107  thr = (duk_hthread *) ctx;
17108  DUK__CHECK_SPACE();
17109 
17110  tv_from = duk_require_tval(ctx, from_idx);
17111  tv_to = thr->valstack_top++;
17112  DUK_ASSERT(tv_from != NULL);
17113  DUK_ASSERT(tv_to != NULL);
17114  DUK_TVAL_SET_TVAL(tv_to, tv_from);
17115  DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
17116 }
17117 
17118 DUK_EXTERNAL void duk_dup_top(duk_context *ctx) {
17119 #if defined(DUK_USE_PREFER_SIZE)
17120  duk_dup(ctx, -1);
17121 #else
17122  duk_hthread *thr;
17123  duk_tval *tv_from;
17124  duk_tval *tv_to;
17125 
17126  DUK_ASSERT_CTX_VALID(ctx);
17127  thr = (duk_hthread *) ctx;
17128  DUK__CHECK_SPACE();
17129 
17130  if (thr->valstack_top - thr->valstack_bottom <= 0) {
17131  DUK_ERROR_RANGE_INDEX(thr, -1);
17132  return; /* unreachable */
17133  }
17134  tv_from = thr->valstack_top - 1;
17135  tv_to = thr->valstack_top++;
17136  DUK_ASSERT(tv_from != NULL);
17137  DUK_ASSERT(tv_to != NULL);
17138  DUK_TVAL_SET_TVAL(tv_to, tv_from);
17139  DUK_TVAL_INCREF(thr, tv_to); /* no side effects */
17140 #endif
17141 }
17142 
17143 DUK_INTERNAL void duk_dup_0(duk_context *ctx) {
17144  duk_dup(ctx, 0);
17145 }
17146 DUK_INTERNAL void duk_dup_1(duk_context *ctx) {
17147  duk_dup(ctx, 1);
17148 }
17149 DUK_INTERNAL void duk_dup_2(duk_context *ctx) {
17150  duk_dup(ctx, 2);
17151 }
17152 DUK_INTERNAL void duk_dup_m2(duk_context *ctx) {
17153  duk_dup(ctx, -2);
17154 }
17155 DUK_INTERNAL void duk_dup_m3(duk_context *ctx) {
17156  duk_dup(ctx, -3);
17157 }
17158 DUK_INTERNAL void duk_dup_m4(duk_context *ctx) {
17159  duk_dup(ctx, -4);
17160 }
17161 
17162 DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_idx) {
17163  duk_tval *p;
17164  duk_tval *q;
17165  duk_tval tv_tmp;
17166  duk_size_t nbytes;
17167 
17168  DUK_ASSERT_CTX_VALID(ctx);
17169 
17170  p = duk_require_tval(ctx, to_idx);
17171  DUK_ASSERT(p != NULL);
17172  q = duk_require_tval(ctx, -1);
17173  DUK_ASSERT(q != NULL);
17174 
17175  DUK_ASSERT(q >= p);
17176 
17177  /* nbytes
17178  * <--------->
17179  * [ ... | p | x | x | q ]
17180  * => [ ... | q | p | x | x ]
17181  */
17182 
17183  nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
17184 
17185  DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
17186  (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
17187 
17188  /* No net refcount changes. */
17189 
17190  if (nbytes > 0) {
17191  DUK_TVAL_SET_TVAL(&tv_tmp, q);
17192  DUK_ASSERT(nbytes > 0);
17193  DUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);
17194  DUK_TVAL_SET_TVAL(p, &tv_tmp);
17195  } else {
17196  /* nop: insert top to top */
17197  DUK_ASSERT(nbytes == 0);
17198  DUK_ASSERT(p == q);
17199  }
17200 }
17201 
17202 DUK_EXTERNAL void duk_replace(duk_context *ctx, duk_idx_t to_idx) {
17203  duk_hthread *thr = (duk_hthread *) ctx;
17204  duk_tval *tv1;
17205  duk_tval *tv2;
17206  duk_tval tv_tmp;
17207 
17208  DUK_ASSERT_CTX_VALID(ctx);
17209 
17210  tv1 = duk_require_tval(ctx, -1);
17211  DUK_ASSERT(tv1 != NULL);
17212  tv2 = duk_require_tval(ctx, to_idx);
17213  DUK_ASSERT(tv2 != NULL);
17214 
17215  /* For tv1 == tv2, both pointing to stack top, the end result
17216  * is same as duk_pop(ctx).
17217  */
17218  DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
17219  DUK_TVAL_SET_TVAL(tv2, tv1);
17220  DUK_TVAL_SET_UNDEFINED(tv1);
17221  thr->valstack_top--;
17222  DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
17223 }
17224 
17225 DUK_EXTERNAL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx) {
17226  duk_hthread *thr = (duk_hthread *) ctx;
17227  duk_tval *tv1;
17228  duk_tval *tv2;
17229 
17230  DUK_ASSERT_CTX_VALID(ctx);
17231  DUK_UNREF(thr); /* w/o refcounting */
17232 
17233  tv1 = duk_require_tval(ctx, from_idx);
17234  DUK_ASSERT(tv1 != NULL);
17235  tv2 = duk_require_tval(ctx, to_idx);
17236  DUK_ASSERT(tv2 != NULL);
17237 
17238  /* For tv1 == tv2, this is a no-op (no explicit check needed). */
17239  DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1); /* side effects */
17240 }
17241 
17242 DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t idx) {
17243  duk_hthread *thr = (duk_hthread *) ctx;
17244  duk_tval *p;
17245  duk_tval *q;
17246 #if defined(DUK_USE_REFERENCE_COUNTING)
17247  duk_tval tv_tmp;
17248 #endif
17249  duk_size_t nbytes;
17250 
17251  DUK_ASSERT_CTX_VALID(ctx);
17252 
17253  p = duk_require_tval(ctx, idx);
17254  DUK_ASSERT(p != NULL);
17255  q = duk_require_tval(ctx, -1);
17256  DUK_ASSERT(q != NULL);
17257 
17258  DUK_ASSERT(q >= p);
17259 
17260  /* nbytes zero size case
17261  * <--------->
17262  * [ ... | p | x | x | q ] [ ... | p==q ]
17263  * => [ ... | x | x | q ] [ ... ]
17264  */
17265 
17266 #if defined(DUK_USE_REFERENCE_COUNTING)
17267  /* use a temp: decref only when valstack reachable values are correct */
17268  DUK_TVAL_SET_TVAL(&tv_tmp, p);
17269 #endif
17270 
17271  nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p)); /* Note: 'q' is top-1 */
17272  DUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes); /* zero size not an issue: pointers are valid */
17273 
17274  DUK_TVAL_SET_UNDEFINED(q);
17275  thr->valstack_top--;
17276 
17277 #if defined(DUK_USE_REFERENCE_COUNTING)
17278  DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
17279 #endif
17280 }
17281 
17282 DUK_INTERNAL_DECL void duk_remove_m2(duk_context *ctx) {
17283  duk_remove(ctx, -2);
17284 }
17285 
17286 /*
17287  * Stack slice primitives
17288  */
17289 
17290 DUK_EXTERNAL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
17291  duk_hthread *to_thr = (duk_hthread *) to_ctx;
17292  duk_hthread *from_thr = (duk_hthread *) from_ctx;
17293  void *src;
17294  duk_size_t nbytes;
17295  duk_tval *p;
17296  duk_tval *q;
17297 
17298  /* XXX: several pointer comparison issues here */
17299 
17300  DUK_ASSERT_CTX_VALID(to_ctx);
17301  DUK_ASSERT_CTX_VALID(from_ctx);
17302  DUK_ASSERT(to_ctx != NULL);
17303  DUK_ASSERT(from_ctx != NULL);
17304 
17305  if (to_ctx == from_ctx) {
17306  DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
17307  return;
17308  }
17309  if ((count < 0) ||
17310  (count > (duk_idx_t) to_thr->valstack_max)) {
17311  /* Maximum value check ensures 'nbytes' won't wrap below. */
17312  DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
17313  return;
17314  }
17315 
17316  nbytes = sizeof(duk_tval) * count;
17317  if (nbytes == 0) {
17318  return;
17319  }
17320  DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
17321  if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
17322  DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
17323  }
17324  src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
17325  if (src < (void *) from_thr->valstack_bottom) {
17326  DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
17327  }
17328 
17329  /* copy values (no overlap even if to_ctx == from_ctx; that's not
17330  * allowed now anyway)
17331  */
17332  DUK_ASSERT(nbytes > 0);
17333  DUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
17334 
17335  p = to_thr->valstack_top;
17336  to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
17337 
17338  if (is_copy) {
17339  /* Incref copies, keep originals. */
17340  q = to_thr->valstack_top;
17341  while (p < q) {
17342  DUK_TVAL_INCREF(to_thr, p); /* no side effects */
17343  p++;
17344  }
17345  } else {
17346  /* No net refcount change. */
17347  p = from_thr->valstack_top;
17348  q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
17349  from_thr->valstack_top = q;
17350 
17351  while (p > q) {
17352  p--;
17353  DUK_TVAL_SET_UNDEFINED(p);
17354  /* XXX: fast primitive to set a bunch of values to UNDEFINED */
17355  }
17356  }
17357 }
17358 
17359 /*
17360  * Get/require
17361  */
17362 
17363 DUK_EXTERNAL void duk_require_undefined(duk_context *ctx, duk_idx_t idx) {
17364  duk_hthread *thr = (duk_hthread *) ctx;
17365  duk_tval *tv;
17366 
17367  DUK_ASSERT_CTX_VALID(ctx);
17368 
17369  tv = duk_get_tval_or_unused(ctx, idx);
17370  DUK_ASSERT(tv != NULL);
17371  if (!DUK_TVAL_IS_UNDEFINED(tv)) {
17372  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
17373  }
17374 }
17375 
17376 DUK_EXTERNAL void duk_require_null(duk_context *ctx, duk_idx_t idx) {
17377  duk_hthread *thr = (duk_hthread *) ctx;
17378  duk_tval *tv;
17379 
17380  DUK_ASSERT_CTX_VALID(ctx);
17381 
17382  tv = duk_get_tval_or_unused(ctx, idx);
17383  DUK_ASSERT(tv != NULL);
17384  if (!DUK_TVAL_IS_NULL(tv)) {
17385  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
17386  }
17387 }
17388 
17389 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t idx) {
17390  duk_bool_t ret = 0; /* default: false */
17391  duk_tval *tv;
17392 
17393  DUK_ASSERT_CTX_VALID(ctx);
17394 
17395  tv = duk_get_tval_or_unused(ctx, idx);
17396  DUK_ASSERT(tv != NULL);
17397  if (DUK_TVAL_IS_BOOLEAN(tv)) {
17398  ret = DUK_TVAL_GET_BOOLEAN(tv);
17399  }
17400 
17401  DUK_ASSERT(ret == 0 || ret == 1);
17402  return ret;
17403 }
17404 
17405 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t idx) {
17406  duk_hthread *thr = (duk_hthread *) ctx;
17407  duk_tval *tv;
17408  duk_bool_t ret;
17409 
17410  DUK_ASSERT_CTX_VALID(ctx);
17411 
17412  tv = duk_get_tval_or_unused(ctx, idx);
17413  DUK_ASSERT(tv != NULL);
17414  if (!DUK_TVAL_IS_BOOLEAN(tv)) {
17415  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
17416  }
17417  ret = DUK_TVAL_GET_BOOLEAN(tv);
17418  DUK_ASSERT(ret == 0 || ret == 1);
17419  return ret;
17420 }
17421 
17422 DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t idx) {
17423  duk_double_union ret;
17424  duk_tval *tv;
17425 
17426  DUK_ASSERT_CTX_VALID(ctx);
17427 
17428  ret.d = DUK_DOUBLE_NAN; /* default: NaN */
17429  tv = duk_get_tval_or_unused(ctx, idx);
17430  DUK_ASSERT(tv != NULL);
17431  if (DUK_TVAL_IS_NUMBER(tv)) {
17432  ret.d = DUK_TVAL_GET_NUMBER(tv);
17433  }
17434 
17435  /* When using packed duk_tval, number must be in NaN-normalized form
17436  * for it to be a duk_tval, so no need to normalize. NOP for unpacked
17437  * duk_tval.
17438  */
17439  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
17440  return ret.d;
17441 }
17442 
17443 DUK_EXTERNAL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t idx) {
17444  duk_hthread *thr = (duk_hthread *) ctx;
17445  duk_tval *tv;
17446  duk_double_union ret;
17447 
17448  DUK_ASSERT_CTX_VALID(ctx);
17449 
17450  tv = duk_get_tval_or_unused(ctx, idx);
17451  DUK_ASSERT(tv != NULL);
17452  if (!DUK_TVAL_IS_NUMBER(tv)) {
17453  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17454  }
17455 
17456  ret.d = DUK_TVAL_GET_NUMBER(tv);
17457 
17458  /* When using packed duk_tval, number must be in NaN-normalized form
17459  * for it to be a duk_tval, so no need to normalize. NOP for unpacked
17460  * duk_tval.
17461  */
17462  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
17463  return ret.d;
17464 }
17465 
17466 DUK_EXTERNAL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t idx) {
17467  /* Custom coercion for API */
17468  DUK_ASSERT_CTX_VALID(ctx);
17469  return (duk_int_t) duk__api_coerce_d2i(ctx, idx, 0 /*require*/);
17470 }
17471 
17472 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t idx) {
17473  /* Custom coercion for API */
17474  DUK_ASSERT_CTX_VALID(ctx);
17475  return (duk_uint_t) duk__api_coerce_d2ui(ctx, idx, 0 /*require*/);
17476 }
17477 
17478 DUK_EXTERNAL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t idx) {
17479  /* Custom coercion for API */
17480  DUK_ASSERT_CTX_VALID(ctx);
17481  return (duk_int_t) duk__api_coerce_d2i(ctx, idx, 1 /*require*/);
17482 }
17483 
17484 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t idx) {
17485  /* Custom coercion for API */
17486  DUK_ASSERT_CTX_VALID(ctx);
17487  return (duk_uint_t) duk__api_coerce_d2ui(ctx, idx, 1 /*require*/);
17488 }
17489 
17490 DUK_EXTERNAL const char *duk_get_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
17491  const char *ret;
17492  duk_tval *tv;
17493 
17494  DUK_ASSERT_CTX_VALID(ctx);
17495 
17496  /* default: NULL, length 0 */
17497  ret = NULL;
17498  if (out_len) {
17499  *out_len = 0;
17500  }
17501 
17502  tv = duk_get_tval_or_unused(ctx, idx);
17503  DUK_ASSERT(tv != NULL);
17504  if (DUK_TVAL_IS_STRING(tv)) {
17505  /* Here we rely on duk_hstring instances always being zero
17506  * terminated even if the actual string is not.
17507  */
17508  duk_hstring *h = DUK_TVAL_GET_STRING(tv);
17509  DUK_ASSERT(h != NULL);
17510  ret = (const char *) DUK_HSTRING_GET_DATA(h);
17511  if (out_len) {
17512  *out_len = DUK_HSTRING_GET_BYTELEN(h);
17513  }
17514  }
17515 
17516  return ret;
17517 }
17518 
17519 DUK_EXTERNAL const char *duk_require_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
17520  duk_hstring *h;
17521 
17522  DUK_ASSERT_CTX_VALID(ctx);
17523 
17524  h = duk_require_hstring(ctx, idx);
17525  DUK_ASSERT(h != NULL);
17526  if (out_len) {
17527  *out_len = DUK_HSTRING_GET_BYTELEN(h);
17528  }
17529  return (const char *) DUK_HSTRING_GET_DATA(h);
17530 }
17531 
17532 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
17533  duk_hstring *h;
17534 
17535  DUK_ASSERT_CTX_VALID(ctx);
17536 
17537  h = duk_require_hstring_notsymbol(ctx, idx);
17538  DUK_ASSERT(h != NULL);
17539  if (out_len) {
17540  *out_len = DUK_HSTRING_GET_BYTELEN(h);
17541  }
17542  return (const char *) DUK_HSTRING_GET_DATA(h);
17543 }
17544 
17545 DUK_EXTERNAL const char *duk_get_string(duk_context *ctx, duk_idx_t idx) {
17546  DUK_ASSERT_CTX_VALID(ctx);
17547 
17548  return duk_get_lstring(ctx, idx, NULL);
17549 }
17550 
17551 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_context *ctx, duk_idx_t idx) {
17552  duk_hstring *h;
17553 
17554  DUK_ASSERT_CTX_VALID(ctx);
17555 
17556  h = duk_get_hstring_notsymbol(ctx, idx);
17557  if (h) {
17558  return (const char *) DUK_HSTRING_GET_DATA(h);
17559  } else {
17560  return NULL;
17561  }
17562 }
17563 
17564 DUK_EXTERNAL const char *duk_require_string(duk_context *ctx, duk_idx_t idx) {
17565  DUK_ASSERT_CTX_VALID(ctx);
17566 
17567  return duk_require_lstring(ctx, idx, NULL);
17568 }
17569 
17570 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_context *ctx, duk_idx_t idx) {
17571  duk_hstring *h;
17572 
17573  DUK_ASSERT_CTX_VALID(ctx);
17574 
17575  h = duk_require_hstring_notsymbol(ctx, idx);
17576  DUK_ASSERT(h != NULL);
17577  return (const char *) DUK_HSTRING_GET_DATA(h);
17578 }
17579 
17580 DUK_EXTERNAL void *duk_get_pointer(duk_context *ctx, duk_idx_t idx) {
17581  duk_tval *tv;
17582  void *p;
17583 
17584  DUK_ASSERT_CTX_VALID(ctx);
17585 
17586  tv = duk_get_tval_or_unused(ctx, idx);
17587  DUK_ASSERT(tv != NULL);
17588  if (!DUK_TVAL_IS_POINTER(tv)) {
17589  return NULL;
17590  }
17591 
17592  p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
17593  return p;
17594 }
17595 
17596 DUK_EXTERNAL void *duk_require_pointer(duk_context *ctx, duk_idx_t idx) {
17597  duk_hthread *thr = (duk_hthread *) ctx;
17598  duk_tval *tv;
17599  void *p;
17600 
17601  DUK_ASSERT_CTX_VALID(ctx);
17602 
17603  /* Note: here we must be wary of the fact that a pointer may be
17604  * valid and be a NULL.
17605  */
17606  tv = duk_get_tval_or_unused(ctx, idx);
17607  DUK_ASSERT(tv != NULL);
17608  if (!DUK_TVAL_IS_POINTER(tv)) {
17609  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
17610  }
17611  p = DUK_TVAL_GET_POINTER(tv); /* may be NULL */
17612  return p;
17613 }
17614 
17615 #if 0 /*unused*/
17616 DUK_INTERNAL void *duk_get_voidptr(duk_context *ctx, duk_idx_t idx) {
17617  duk_tval *tv;
17618  duk_heaphdr *h;
17619 
17620  DUK_ASSERT_CTX_VALID(ctx);
17621 
17622  tv = duk_get_tval_or_unused(ctx, idx);
17623  DUK_ASSERT(tv != NULL);
17624  if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
17625  return NULL;
17626  }
17627 
17628  h = DUK_TVAL_GET_HEAPHDR(tv);
17629  DUK_ASSERT(h != NULL);
17630  return (void *) h;
17631 }
17632 #endif
17633 
17634 DUK_LOCAL void *duk__get_buffer_helper(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_bool_t throw_flag) {
17635  duk_hthread *thr = (duk_hthread *) ctx;
17636  duk_tval *tv;
17637  duk_hbuffer *h;
17638 
17639  DUK_ASSERT_CTX_VALID(ctx);
17640  DUK_UNREF(thr);
17641 
17642  if (out_size != NULL) {
17643  *out_size = 0;
17644  }
17645 
17646  tv = duk_get_tval_or_unused(ctx, idx);
17647  DUK_ASSERT(tv != NULL);
17648  if (!DUK_TVAL_IS_BUFFER(tv)) {
17649  if (throw_flag) {
17650  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
17651  }
17652  return NULL;
17653  }
17654 
17655  h = DUK_TVAL_GET_BUFFER(tv);
17656  DUK_ASSERT(h != NULL);
17657  if (out_size) {
17658  *out_size = DUK_HBUFFER_GET_SIZE(h);
17659  }
17660  return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
17661 }
17662 
17663 DUK_EXTERNAL void *duk_get_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size) {
17664  return duk__get_buffer_helper(ctx, idx, out_size, 0 /*throw_flag*/);
17665 }
17666 
17667 DUK_EXTERNAL void *duk_require_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size) {
17668  return duk__get_buffer_helper(ctx, idx, out_size, 1 /*throw_flag*/);
17669 }
17670 
17671 /* Get the active buffer data area for a plain buffer or a buffer object.
17672  * Return NULL if the the value is not a buffer. Note that a buffer may
17673  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
17674  * argument allows caller to detect this reliably.
17675  */
17676 DUK_INTERNAL void *duk_get_buffer_data_raw(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_bool_t throw_flag, duk_bool_t *out_isbuffer) {
17677  duk_hthread *thr = (duk_hthread *) ctx;
17678  duk_tval *tv;
17679 
17680  DUK_ASSERT_CTX_VALID(ctx);
17681  DUK_UNREF(thr);
17682 
17683  if (out_isbuffer != NULL) {
17684  *out_isbuffer = 0;
17685  }
17686  if (out_size != NULL) {
17687  *out_size = 0;
17688  }
17689 
17690  tv = duk_get_tval_or_unused(ctx, idx);
17691  DUK_ASSERT(tv != NULL);
17692 
17693  if (DUK_TVAL_IS_BUFFER(tv)) {
17694  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
17695  DUK_ASSERT(h != NULL);
17696  if (out_size != NULL) {
17697  *out_size = DUK_HBUFFER_GET_SIZE(h);
17698  }
17699  if (out_isbuffer != NULL) {
17700  *out_isbuffer = 1;
17701  }
17702  return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h); /* may be NULL (but only if size is 0) */
17703  }
17704 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
17705  else if (DUK_TVAL_IS_OBJECT(tv)) {
17706  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
17707  DUK_ASSERT(h != NULL);
17708  if (DUK_HOBJECT_IS_BUFOBJ(h)) {
17709  /* XXX: this is probably a useful shared helper: for a
17710  * duk_hbufobj, get a validated buffer pointer/length.
17711  */
17712  duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
17713  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
17714 
17715  if (h_bufobj->buf != NULL &&
17716  DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
17717  duk_uint8_t *p;
17718 
17719  p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
17720  if (out_size != NULL) {
17721  *out_size = (duk_size_t) h_bufobj->length;
17722  }
17723  if (out_isbuffer != NULL) {
17724  *out_isbuffer = 1;
17725  }
17726  return (void *) (p + h_bufobj->offset);
17727  }
17728  /* if slice not fully valid, treat as error */
17729  }
17730  }
17731 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
17732 
17733  if (throw_flag) {
17734  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
17735  }
17736  return NULL;
17737 }
17738 
17739 DUK_EXTERNAL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size) {
17740  return duk_get_buffer_data_raw(ctx, idx, out_size, 0 /*throw_flag*/, NULL);
17741 }
17742 
17743 DUK_EXTERNAL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size) {
17744  return duk_get_buffer_data_raw(ctx, idx, out_size, 1 /*throw_flag*/, NULL);
17745 }
17746 
17747 /* Raw helper for getting a value from the stack, checking its tag.
17748  * The tag cannot be a number because numbers don't have an internal
17749  * tag in the packed representation.
17750  */
17751 
17752 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_context *ctx, duk_idx_t idx, duk_uint_t tag) {
17753  duk_tval *tv;
17754  duk_heaphdr *ret;
17755 
17756  DUK_ASSERT_CTX_VALID(ctx);
17757 
17758  tv = duk_get_tval_or_unused(ctx, idx);
17759  DUK_ASSERT(tv != NULL);
17760  if (DUK_TVAL_GET_TAG(tv) != tag) {
17761  return (duk_heaphdr *) NULL;
17762  }
17763 
17764  ret = DUK_TVAL_GET_HEAPHDR(tv);
17765  DUK_ASSERT(ret != NULL); /* tagged null pointers should never occur */
17766  return ret;
17767 
17768 }
17769 
17770 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_context *ctx, duk_idx_t idx) {
17771  return (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_STRING);
17772 }
17773 
17774 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_context *ctx, duk_idx_t idx) {
17775  duk_hstring *res = (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_STRING);
17776  if (res && DUK_HSTRING_HAS_SYMBOL(res)) {
17777  return NULL;
17778  }
17779  return res;
17780 }
17781 
17782 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_context *ctx, duk_idx_t idx) {
17783  duk_hstring *h;
17784  h = (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_STRING);
17785  if (h == NULL) {
17786  DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, idx, "string", DUK_STR_NOT_STRING);
17787  }
17788  return h;
17789 }
17790 
17791 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_context *ctx, duk_idx_t idx) {
17792  duk_hstring *h;
17793  h = (duk_hstring *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_STRING);
17794  if (h == NULL || DUK_HSTRING_HAS_SYMBOL(h)) {
17795  DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, idx, "string", DUK_STR_NOT_STRING);
17796  }
17797  return h;
17798 }
17799 
17800 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_context *ctx, duk_idx_t idx) {
17801  return (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17802 }
17803 
17804 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_context *ctx, duk_idx_t idx) {
17805  duk_hobject *h;
17806  h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17807  if (h == NULL) {
17808  DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, idx, "object", DUK_STR_NOT_OBJECT);
17809  }
17810  return h;
17811 }
17812 
17813 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_context *ctx, duk_idx_t idx) {
17814  return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_BUFFER);
17815 }
17816 
17817 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_context *ctx, duk_idx_t idx) {
17818  duk_hbuffer *h;
17819  h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_BUFFER);
17820  if (h == NULL) {
17821  DUK_ERROR_REQUIRE_TYPE_INDEX(ctx, idx, "buffer", DUK_STR_NOT_BUFFER);
17822  }
17823  return h;
17824 }
17825 
17826 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_context *ctx, duk_idx_t idx) {
17827  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17828  if (h != NULL && !DUK_HOBJECT_IS_THREAD(h)) {
17829  h = NULL;
17830  }
17831  return (duk_hthread *) h;
17832 }
17833 
17834 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_context *ctx, duk_idx_t idx) {
17835  duk_hthread *thr = (duk_hthread *) ctx;
17836  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17837  if (!(h != NULL && DUK_HOBJECT_IS_THREAD(h))) {
17838  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
17839  }
17840  return (duk_hthread *) h;
17841 }
17842 
17843 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_context *ctx, duk_idx_t idx) {
17844  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17845  if (h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h)) {
17846  h = NULL;
17847  }
17848  return (duk_hcompfunc *) h;
17849 }
17850 
17851 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_context *ctx, duk_idx_t idx) {
17852  duk_hthread *thr = (duk_hthread *) ctx;
17853  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17854  if (!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h))) {
17855  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
17856  }
17857  return (duk_hcompfunc *) h;
17858 }
17859 
17860 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_context *ctx, duk_idx_t idx) {
17861  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17862  if (h != NULL && !DUK_HOBJECT_IS_NATFUNC(h)) {
17863  h = NULL;
17864  }
17865  return (duk_hnatfunc *) h;
17866 }
17867 
17868 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_context *ctx, duk_idx_t idx) {
17869  duk_hthread *thr = (duk_hthread *) ctx;
17870  duk_hobject *h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
17871  if (!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h))) {
17872  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
17873  }
17874  return (duk_hnatfunc *) h;
17875 }
17876 
17877 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t idx) {
17878  duk_tval *tv;
17879  duk_hobject *h;
17880  duk_hnatfunc *f;
17881 
17882  DUK_ASSERT_CTX_VALID(ctx);
17883 
17884  tv = duk_get_tval_or_unused(ctx, idx);
17885  DUK_ASSERT(tv != NULL);
17886  if (!DUK_TVAL_IS_OBJECT(tv)) {
17887  return NULL;
17888  }
17889  h = DUK_TVAL_GET_OBJECT(tv);
17890  DUK_ASSERT(h != NULL);
17891 
17892  if (!DUK_HOBJECT_IS_NATFUNC(h)) {
17893  return NULL;
17894  }
17895  DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
17896  f = (duk_hnatfunc *) h;
17897 
17898  return f->func;
17899 }
17900 
17901 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t idx) {
17902  duk_hthread *thr = (duk_hthread *) ctx;
17903  duk_c_function ret;
17904 
17905  DUK_ASSERT_CTX_VALID(ctx);
17906 
17907  ret = duk_get_c_function(ctx, idx);
17908  if (!ret) {
17909  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
17910  }
17911  return ret;
17912 }
17913 
17914 DUK_EXTERNAL void duk_require_function(duk_context *ctx, duk_idx_t idx) {
17915  if (!duk_is_function(ctx, idx)) {
17916  DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, idx, "function", DUK_STR_NOT_FUNCTION);
17917  }
17918 }
17919 
17920 DUK_INTERNAL_DECL void duk_require_constructable(duk_context *ctx, duk_idx_t idx) {
17921  duk_hobject *h;
17922 
17923  h = duk_require_hobject_accept_mask(ctx, idx, DUK_TYPE_MASK_LIGHTFUNC);
17924  if (h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
17925  DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
17926  }
17927  /* Lightfuncs (h == NULL) are constructable. */
17928 }
17929 
17930 DUK_EXTERNAL duk_context *duk_get_context(duk_context *ctx, duk_idx_t idx) {
17931  DUK_ASSERT_CTX_VALID(ctx);
17932 
17933  return (duk_context *) duk_get_hthread(ctx, idx);
17934 }
17935 
17936 DUK_EXTERNAL duk_context *duk_require_context(duk_context *ctx, duk_idx_t idx) {
17937  DUK_ASSERT_CTX_VALID(ctx);
17938 
17939  return (duk_context *) duk_require_hthread(ctx, idx);
17940 }
17941 
17942 DUK_EXTERNAL void *duk_get_heapptr(duk_context *ctx, duk_idx_t idx) {
17943  duk_tval *tv;
17944  void *ret;
17945 
17946  DUK_ASSERT_CTX_VALID(ctx);
17947 
17948  tv = duk_get_tval_or_unused(ctx, idx);
17949  DUK_ASSERT(tv != NULL);
17950  if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
17951  return (void *) NULL;
17952  }
17953 
17954  ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
17955  DUK_ASSERT(ret != NULL);
17956  return ret;
17957 }
17958 
17959 DUK_EXTERNAL void *duk_require_heapptr(duk_context *ctx, duk_idx_t idx) {
17960  duk_hthread *thr = (duk_hthread *) ctx;
17961  duk_tval *tv;
17962  void *ret;
17963 
17964  DUK_ASSERT_CTX_VALID(ctx);
17965 
17966  tv = duk_get_tval_or_unused(ctx, idx);
17967  DUK_ASSERT(tv != NULL);
17968  if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
17969  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
17970  }
17971 
17972  ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
17973  DUK_ASSERT(ret != NULL);
17974  return ret;
17975 }
17976 
17977 /* Internal helper for getting/requiring a duk_hobject with possible promotion. */
17978 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask) {
17979  duk_uint_t val_mask;
17980  duk_hobject *res;
17981 
17982  DUK_ASSERT_CTX_VALID(ctx);
17983 
17984  res = duk_get_hobject(ctx, idx); /* common case, not promoted */
17985  if (res != NULL) {
17986  DUK_ASSERT(res != NULL);
17987  return res;
17988  }
17989 
17990  val_mask = duk_get_type_mask(ctx, idx);
17991  if (val_mask & type_mask) {
17992  if (type_mask & DUK_TYPE_MASK_PROMOTE) {
17993  res = duk_to_hobject(ctx, idx);
17994  DUK_ASSERT(res != NULL);
17995  return res;
17996  } else {
17997  return NULL; /* accept without promoting */
17998  }
17999  }
18000 
18001  if (type_mask & DUK_TYPE_MASK_THROW) {
18002  DUK_ERROR_REQUIRE_TYPE_INDEX((duk_hthread *) ctx, idx, "object", DUK_STR_NOT_OBJECT);
18003  }
18004  return NULL;
18005 }
18006 
18007 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
18008  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
18009  * This is useful for call sites which want an object but also accept a plain
18010  * buffer and/or a lightfunc which gets automatically promoted to an object.
18011  * Return value is NULL if value is neither an object nor a plain type allowed
18012  * by the mask.
18013  */
18014 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask) {
18015  return duk__get_hobject_promote_mask_raw(ctx, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
18016 }
18017 
18018 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
18019  * returning a NULL.
18020  */
18021 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask) {
18022  return duk__get_hobject_promote_mask_raw(ctx, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
18023 }
18024 
18025 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
18026  * supplied 'type_mask', return a NULL instead. Otherwise throw a TypeError.
18027  */
18028 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t type_mask) {
18029  return duk__get_hobject_promote_mask_raw(ctx, idx, type_mask | DUK_TYPE_MASK_THROW);
18030 }
18031 
18032 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_context *ctx, duk_idx_t idx, duk_small_uint_t classnum) {
18033  duk_hobject *h;
18034 
18035  DUK_ASSERT_CTX_VALID(ctx);
18036  DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
18037  DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
18038 
18039  h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
18040  if (h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum) {
18041  h = NULL;
18042  }
18043  return h;
18044 }
18045 
18046 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_context *ctx, duk_idx_t idx, duk_small_uint_t classnum) {
18047  duk_hthread *thr;
18048  duk_hobject *h;
18049 
18050  DUK_ASSERT_CTX_VALID(ctx);
18051  DUK_ASSERT_DISABLE(classnum >= 0); /* unsigned */
18052  DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
18053  thr = (duk_hthread *) ctx;
18054 
18055  h = (duk_hobject *) duk__get_tagged_heaphdr_raw(ctx, idx, DUK_TAG_OBJECT);
18056  if (!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum)) {
18057  duk_hstring *h_class;
18058  h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
18059  DUK_UNREF(h_class);
18060 
18061  DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
18062  }
18063  return h;
18064 }
18065 
18066 DUK_EXTERNAL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t idx) {
18067  duk_tval *tv;
18068 
18069  DUK_ASSERT_CTX_VALID(ctx);
18070 
18071  tv = duk_get_tval_or_unused(ctx, idx);
18072  DUK_ASSERT(tv != NULL);
18073 
18074  switch (DUK_TVAL_GET_TAG(tv)) {
18075  case DUK_TAG_UNDEFINED:
18076  case DUK_TAG_NULL:
18077  case DUK_TAG_BOOLEAN:
18078  case DUK_TAG_POINTER:
18079  return 0;
18080 #if defined(DUK_USE_PREFER_SIZE)
18081  /* All of these types (besides object) have a virtual, non-configurable
18082  * .length property which is within size_t range so we can just look it
18083  * up without specific type checks.
18084  */
18085  case DUK_TAG_STRING:
18086  case DUK_TAG_BUFFER:
18087  case DUK_TAG_LIGHTFUNC: {
18088  duk_size_t ret;
18089  duk_get_prop_stridx(ctx, idx, DUK_STRIDX_LENGTH);
18090  ret = (duk_size_t) duk_to_number_m1(ctx);
18091  duk_pop(ctx);
18092  return ret;
18093  }
18094 #else /* DUK_USE_PREFER_SIZE */
18095  case DUK_TAG_STRING: {
18096  duk_hstring *h = DUK_TVAL_GET_STRING(tv);
18097  DUK_ASSERT(h != NULL);
18098  if (DUK_HSTRING_HAS_SYMBOL(h)) {
18099  return 0;
18100  }
18101  return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
18102  }
18103  case DUK_TAG_BUFFER: {
18104  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
18105  DUK_ASSERT(h != NULL);
18106  return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
18107  }
18108  case DUK_TAG_LIGHTFUNC: {
18109  duk_small_uint_t lf_flags;
18110  lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
18111  return (duk_size_t) DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
18112  }
18113 #endif /* DUK_USE_PREFER_SIZE */
18114  case DUK_TAG_OBJECT: {
18115  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
18116  DUK_ASSERT(h != NULL);
18117  return (duk_size_t) duk_hobject_get_length((duk_hthread *) ctx, h);
18118  }
18119 #if defined(DUK_USE_FASTINT)
18120  case DUK_TAG_FASTINT:
18121 #endif
18122  default:
18123  /* number or 'unused' */
18124  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
18125  return 0;
18126  }
18127 
18128  DUK_UNREACHABLE();
18129 }
18130 
18131 /*
18132  * duk_known_xxx() helpers
18133  *
18134  * Used internally when we're 100% sure that a certain index is valid and
18135  * contains an object of a certain type. For example, if we duk_push_object()
18136  * we can then safely duk_known_hobject(ctx, -1). These helpers just assert
18137  * for the index and type, and if the assumptions are not valid, memory unsafe
18138  * behavior happens.
18139  */
18140 
18141 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_context *ctx, duk_idx_t idx) {
18142  duk_hthread *thr = (duk_hthread *) ctx;
18143  duk_tval *tv;
18144  duk_heaphdr *h;
18145 
18146  DUK_ASSERT_CTX_VALID(ctx);
18147  if (idx < 0) {
18148  tv = thr->valstack_top + idx;
18149  } else {
18150  tv = thr->valstack_bottom + idx;
18151  }
18152  DUK_ASSERT(tv >= thr->valstack_bottom);
18153  DUK_ASSERT(tv < thr->valstack_top);
18154  h = DUK_TVAL_GET_HEAPHDR(tv);
18155  DUK_ASSERT(h != NULL);
18156  return h;
18157 }
18158 
18159 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_context *ctx, duk_idx_t idx) {
18160  DUK_ASSERT(duk_get_hstring(ctx, idx) != NULL);
18161  return (duk_hstring *) duk__known_heaphdr(ctx, idx);
18162 }
18163 
18164 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_context *ctx, duk_idx_t idx) {
18165  DUK_ASSERT(duk_get_hobject(ctx, idx) != NULL);
18166  return (duk_hobject *) duk__known_heaphdr(ctx, idx);
18167 }
18168 
18169 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_context *ctx, duk_idx_t idx) {
18170  DUK_ASSERT(duk_get_hbuffer(ctx, idx) != NULL);
18171  return (duk_hbuffer *) duk__known_heaphdr(ctx, idx);
18172 }
18173 
18174 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_context *ctx, duk_idx_t idx) {
18175  DUK_ASSERT(duk_get_hcompfunc(ctx, idx) != NULL);
18176  return (duk_hcompfunc *) duk__known_heaphdr(ctx, idx);
18177 }
18178 
18179 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_context *ctx, duk_idx_t idx) {
18180  DUK_ASSERT(duk_get_hnatfunc(ctx, idx) != NULL);
18181  return (duk_hnatfunc *) duk__known_heaphdr(ctx, idx);
18182 }
18183 
18184 DUK_EXTERNAL void duk_set_length(duk_context *ctx, duk_idx_t idx, duk_size_t len) {
18185  DUK_ASSERT_CTX_VALID(ctx);
18186 
18187  idx = duk_normalize_index(ctx, idx);
18188  duk_push_uint(ctx, (duk_uint_t) len);
18189  duk_put_prop_stridx(ctx, idx, DUK_STRIDX_LENGTH);
18190 }
18191 
18192 /*
18193  * Conversions and coercions
18194  *
18195  * The conversion/coercions are in-place operations on the value stack.
18196  * Some operations are implemented here directly, while others call a
18197  * helper in duk_js_ops.c after validating arguments.
18198  */
18199 
18200 /* E5 Section 8.12.8 */
18201 
18202 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_context *ctx, duk_idx_t idx, duk_small_int_t func_stridx) {
18203  if (duk_get_prop_stridx(ctx, idx, func_stridx)) {
18204  /* [ ... func ] */
18205  if (duk_is_callable(ctx, -1)) {
18206  duk_dup(ctx, idx); /* -> [ ... func this ] */
18207  duk_call_method(ctx, 0); /* -> [ ... retval ] */
18208  if (duk_is_primitive(ctx, -1)) {
18209  duk_replace(ctx, idx);
18210  return 1;
18211  }
18212  /* [ ... retval ]; popped below */
18213  }
18214  }
18215  duk_pop(ctx); /* [ ... func/retval ] -> [ ... ] */
18216  return 0;
18217 }
18218 
18219 DUK_EXTERNAL void duk_to_undefined(duk_context *ctx, duk_idx_t idx) {
18220  duk_hthread *thr = (duk_hthread *) ctx;
18221  duk_tval *tv;
18222 
18223  DUK_ASSERT_CTX_VALID(ctx);
18224  DUK_UNREF(thr);
18225 
18226  tv = duk_require_tval(ctx, idx);
18227  DUK_ASSERT(tv != NULL);
18228  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
18229 }
18230 
18231 DUK_EXTERNAL void duk_to_null(duk_context *ctx, duk_idx_t idx) {
18232  duk_hthread *thr = (duk_hthread *) ctx;
18233  duk_tval *tv;
18234 
18235  DUK_ASSERT_CTX_VALID(ctx);
18236  DUK_UNREF(thr);
18237 
18238  tv = duk_require_tval(ctx, idx);
18239  DUK_ASSERT(tv != NULL);
18240  DUK_TVAL_SET_NULL_UPDREF(thr, tv); /* side effects */
18241 }
18242 
18243 /* E5 Section 9.1 */
18244 DUK_EXTERNAL void duk_to_primitive(duk_context *ctx, duk_idx_t idx, duk_int_t hint) {
18245  duk_hthread *thr = (duk_hthread *) ctx;
18246  /* inline initializer for coercers[] is not allowed by old compilers like BCC */
18247  duk_small_int_t coercers[2];
18248  duk_small_uint_t class_number;
18249 
18250  DUK_ASSERT_CTX_VALID(ctx);
18251  DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
18252 
18253  idx = duk_require_normalize_index(ctx, idx);
18254 
18255  if (!duk_check_type_mask(ctx, idx, DUK_TYPE_MASK_OBJECT |
18256  DUK_TYPE_MASK_LIGHTFUNC |
18257  DUK_TYPE_MASK_BUFFER)) {
18258  /* Any other values stay as is. */
18259  DUK_ASSERT(!duk_is_buffer(ctx, idx)); /* duk_to_string() relies on this behavior */
18260  return;
18261  }
18262 
18263  class_number = duk_get_class_number(ctx, idx);
18264 
18265  /* XXX: Symbol objects normally coerce via the ES2015-revised ToPrimitive()
18266  * algorithm which consults value[@@toPrimitive] and avoids calling
18267  * .valueOf() and .toString(). Before that is implemented, special
18268  * case Symbol objects to behave as if they had the default @@toPrimitive
18269  * algorithm of E6 Section 19.4.3.4, i.e. return the plain symbol value
18270  * with no further side effects.
18271  */
18272 
18273  if (class_number == DUK_HOBJECT_CLASS_SYMBOL) {
18274  duk_hobject *h_obj;
18275  duk_hstring *h_str;
18276 
18277  /* XXX: pretty awkward, index based API for internal value access? */
18278  h_obj = duk_known_hobject(ctx, idx);
18279  h_str = duk_hobject_get_internal_value_string(thr->heap, h_obj);
18280  if (h_str) {
18281  duk_push_hstring(ctx, h_str);
18282  duk_replace(ctx, idx);
18283  return;
18284  }
18285  }
18286 
18287 
18288  /* Objects are coerced based on E5 specification.
18289  * Lightfuncs are coerced because they behave like
18290  * objects even if they're internally a primitive
18291  * type. Same applies to plain buffers, which behave
18292  * like ArrayBuffer objects since Duktape 2.x.
18293  */
18294 
18295  coercers[0] = DUK_STRIDX_VALUE_OF;
18296  coercers[1] = DUK_STRIDX_TO_STRING;
18297 
18298  if (hint == DUK_HINT_NONE) {
18299  if (class_number == DUK_HOBJECT_CLASS_DATE) {
18300  hint = DUK_HINT_STRING;
18301  } else {
18302  hint = DUK_HINT_NUMBER;
18303  }
18304  }
18305 
18306  if (hint == DUK_HINT_STRING) {
18307  coercers[0] = DUK_STRIDX_TO_STRING;
18308  coercers[1] = DUK_STRIDX_VALUE_OF;
18309  }
18310 
18311  if (duk__defaultvalue_coerce_attempt(ctx, idx, coercers[0])) {
18312  DUK_ASSERT(!duk_is_buffer(ctx, idx)); /* duk_to_string() relies on this behavior */
18313  return;
18314  }
18315 
18316  if (duk__defaultvalue_coerce_attempt(ctx, idx, coercers[1])) {
18317  DUK_ASSERT(!duk_is_buffer(ctx, idx)); /* duk_to_string() relies on this behavior */
18318  return;
18319  }
18320 
18321  DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
18322 }
18323 
18324 /* E5 Section 9.2 */
18325 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t idx) {
18326  duk_hthread *thr = (duk_hthread *) ctx;
18327  duk_tval *tv;
18328  duk_bool_t val;
18329 
18330  DUK_ASSERT_CTX_VALID(ctx);
18331  DUK_UNREF(thr);
18332 
18333  idx = duk_require_normalize_index(ctx, idx);
18334  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
18335  DUK_ASSERT(tv != NULL);
18336 
18337  val = duk_js_toboolean(tv);
18338  DUK_ASSERT(val == 0 || val == 1);
18339 
18340  /* Note: no need to re-lookup tv, conversion is side effect free. */
18341  DUK_ASSERT(tv != NULL);
18342  DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val); /* side effects */
18343  return val;
18344 }
18345 
18346 DUK_EXTERNAL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t idx) {
18347  duk_hthread *thr = (duk_hthread *) ctx;
18348  duk_tval *tv;
18349  duk_double_t d;
18350 
18351  DUK_ASSERT_CTX_VALID(ctx);
18352 
18353  /* XXX: No need to normalize; the whole operation could be inlined here to
18354  * avoid 'tv' re-lookup.
18355  */
18356  idx = duk_require_normalize_index(ctx, idx);
18357  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
18358  DUK_ASSERT(tv != NULL);
18359  d = duk_js_tonumber(thr, tv); /* XXX: fastint coercion? now result will always be a non-fastint */
18360 
18361  /* ToNumber() may have side effects so must relookup 'tv'. */
18362  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
18363  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
18364  return d;
18365 }
18366 
18367 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_context *ctx) {
18368  return duk_to_number(ctx, -1);
18369 }
18370 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_context *ctx) {
18371  return duk_to_number(ctx, -2);
18372 }
18373 
18374 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_context *ctx, duk_tval *tv) {
18375  duk_double_t res;
18376 
18377  DUK_ASSERT_CTX_VALID(ctx);
18378 
18379  duk_push_tval(ctx, tv);
18380  res = duk_to_number(ctx, -1);
18381  duk_pop(ctx);
18382  return res;
18383 }
18384 
18385 /* XXX: combine all the integer conversions: they share everything
18386  * but the helper function for coercion.
18387  */
18388 
18389 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
18390 
18391 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_context *ctx, duk_idx_t idx, duk__toint_coercer coerce_func) {
18392  duk_hthread *thr = (duk_hthread *) ctx;
18393  duk_tval *tv;
18394  duk_double_t d;
18395 
18396  DUK_ASSERT_CTX_VALID(ctx);
18397 
18398  tv = duk_require_tval(ctx, idx);
18399  DUK_ASSERT(tv != NULL);
18400  d = coerce_func(thr, tv);
18401 
18402  /* XXX: fastint? */
18403 
18404  /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
18405  tv = duk_require_tval(ctx, idx);
18406  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d); /* side effects */
18407  return d;
18408 }
18409 
18410 DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t idx) {
18411  /* Value coercion (in stack): ToInteger(), E5 Section 9.4
18412  * API return value coercion: custom
18413  */
18414  DUK_ASSERT_CTX_VALID(ctx);
18415  (void) duk__to_int_uint_helper(ctx, idx, duk_js_tointeger);
18416  return (duk_int_t) duk__api_coerce_d2i(ctx, idx, 0 /*require*/);
18417 }
18418 
18419 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t idx) {
18420  /* Value coercion (in stack): ToInteger(), E5 Section 9.4
18421  * API return value coercion: custom
18422  */
18423  DUK_ASSERT_CTX_VALID(ctx);
18424  (void) duk__to_int_uint_helper(ctx, idx, duk_js_tointeger);
18425  return (duk_uint_t) duk__api_coerce_d2ui(ctx, idx, 0 /*require*/);
18426 }
18427 
18428 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t idx) {
18429  duk_hthread *thr = (duk_hthread *) ctx;
18430  duk_tval *tv;
18431  duk_int32_t ret;
18432 
18433  DUK_ASSERT_CTX_VALID(ctx);
18434 
18435  tv = duk_require_tval(ctx, idx);
18436  DUK_ASSERT(tv != NULL);
18437  ret = duk_js_toint32(thr, tv);
18438 
18439  /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
18440  tv = duk_require_tval(ctx, idx);
18441  DUK_TVAL_SET_I32_UPDREF(thr, tv, ret); /* side effects */
18442  return ret;
18443 }
18444 
18445 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t idx) {
18446  duk_hthread *thr = (duk_hthread *) ctx;
18447  duk_tval *tv;
18448  duk_uint32_t ret;
18449 
18450  DUK_ASSERT_CTX_VALID(ctx);
18451 
18452  tv = duk_require_tval(ctx, idx);
18453  DUK_ASSERT(tv != NULL);
18454  ret = duk_js_touint32(thr, tv);
18455 
18456  /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
18457  tv = duk_require_tval(ctx, idx);
18458  DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
18459  return ret;
18460 }
18461 
18462 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t idx) {
18463  duk_hthread *thr = (duk_hthread *) ctx;
18464  duk_tval *tv;
18465  duk_uint16_t ret;
18466 
18467  DUK_ASSERT_CTX_VALID(ctx);
18468 
18469  tv = duk_require_tval(ctx, idx);
18470  DUK_ASSERT(tv != NULL);
18471  ret = duk_js_touint16(thr, tv);
18472 
18473  /* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
18474  tv = duk_require_tval(ctx, idx);
18475  DUK_TVAL_SET_U32_UPDREF(thr, tv, ret); /* side effects */
18476  return ret;
18477 }
18478 
18479 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
18480 /* Special coercion for Uint8ClampedArray. */
18481 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_context *ctx, duk_idx_t idx) {
18482  duk_double_t d;
18483  duk_double_t t;
18484  duk_uint8_t ret;
18485 
18486  /* XXX: Simplify this algorithm, should be possible to come up with
18487  * a shorter and faster algorithm by inspecting IEEE representation
18488  * directly.
18489  */
18490 
18491  d = duk_to_number(ctx, idx);
18492  if (d <= 0.0) {
18493  return 0;
18494  } else if (d >= 255) {
18495  return 255;
18496  } else if (DUK_ISNAN(d)) {
18497  /* Avoid NaN-to-integer coercion as it is compiler specific. */
18498  return 0;
18499  }
18500 
18501  t = d - DUK_FLOOR(d);
18502  if (t == 0.5) {
18503  /* Exact halfway, round to even. */
18504  ret = (duk_uint8_t) d;
18505  ret = (ret + 1) & 0xfe; /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
18506  * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
18507  */
18508  } else {
18509  /* Not halfway, round to nearest. */
18510  ret = (duk_uint8_t) (d + 0.5);
18511  }
18512  return ret;
18513 }
18514 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
18515 
18516 DUK_EXTERNAL const char *duk_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
18517  DUK_ASSERT_CTX_VALID(ctx);
18518 
18519  (void) duk_to_string(ctx, idx);
18520  DUK_ASSERT(duk_is_string(ctx, idx));
18521  return duk_require_lstring(ctx, idx, out_len);
18522 }
18523 
18524 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_context *ctx, void *udata) {
18525  DUK_ASSERT_CTX_VALID(ctx);
18526  DUK_UNREF(udata);
18527 
18528  duk_to_string(ctx, -1);
18529  return 1;
18530 }
18531 
18532 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len) {
18533  DUK_ASSERT_CTX_VALID(ctx);
18534 
18535  idx = duk_require_normalize_index(ctx, idx);
18536 
18537  /* We intentionally ignore the duk_safe_call() return value and only
18538  * check the output type. This way we don't also need to check that
18539  * the returned value is indeed a string in the success case.
18540  */
18541 
18542  duk_dup(ctx, idx);
18543  (void) duk_safe_call(ctx, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
18544  if (!duk_is_string(ctx, -1)) {
18545  /* Error: try coercing error to string once. */
18546  (void) duk_safe_call(ctx, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
18547  if (!duk_is_string(ctx, -1)) {
18548  /* Double error */
18549  duk_pop(ctx);
18550  duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_ERROR);
18551  } else {
18552  ;
18553  }
18554  } else {
18555  /* String; may be a symbol, accepted. */
18556  ;
18557  }
18558  DUK_ASSERT(duk_is_string(ctx, -1));
18559 
18560  duk_replace(ctx, idx);
18561  DUK_ASSERT(duk_get_string(ctx, idx) != NULL);
18562  return duk_get_lstring(ctx, idx, out_len);
18563 }
18564 
18565 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_context *ctx, duk_idx_t idx) {
18566  duk_hstring *h;
18567 
18568  DUK_ASSERT_CTX_VALID(ctx);
18569 
18570  duk_to_primitive(ctx, idx, DUK_HINT_STRING); /* needed for e.g. Symbol objects */
18571  h = duk_get_hstring(ctx, idx);
18572  if (h == NULL) {
18573  /* The "is string?" check may seem unnecessary, but as things
18574  * are duk_to_hstring() invokes ToString() which fails for
18575  * symbols. But since symbols are already strings for Duktape
18576  * C API, we check for that before doing the coercion.
18577  */
18578  h = duk_to_hstring(ctx, idx);
18579  }
18580  DUK_ASSERT(h != NULL);
18581  return h;
18582 }
18583 
18584 #if defined(DUK_USE_DEBUGGER_SUPPORT) /* only needed by debugger for now */
18585 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_context *ctx, duk_idx_t idx) {
18586  (void) duk_safe_to_string(ctx, idx);
18587  DUK_ASSERT(duk_is_string(ctx, idx));
18588  DUK_ASSERT(duk_get_hstring(ctx, idx) != NULL);
18589  return duk_known_hstring(ctx, idx);
18590 }
18591 #endif
18592 
18593 /* Push Object.prototype.toString() output for 'tv'. */
18594 DUK_INTERNAL void duk_push_class_string_tval(duk_context *ctx, duk_tval *tv) {
18595  duk_hthread *thr;
18596  duk_small_uint_t stridx;
18597  duk_hstring *h_strclass;
18598 
18599  DUK_ASSERT_CTX_VALID(ctx);
18600  thr = (duk_hthread *) ctx;
18601  DUK_UNREF(thr);
18602 
18603  switch (DUK_TVAL_GET_TAG(tv)) {
18604  case DUK_TAG_UNUSED: /* Treat like 'undefined', shouldn't happen. */
18605  case DUK_TAG_UNDEFINED: {
18606  stridx = DUK_STRIDX_UC_UNDEFINED;
18607  break;
18608  }
18609  case DUK_TAG_NULL: {
18610  stridx = DUK_STRIDX_UC_NULL;
18611  break;
18612  }
18613  case DUK_TAG_BOOLEAN: {
18614  stridx = DUK_STRIDX_UC_BOOLEAN;
18615  break;
18616  }
18617  case DUK_TAG_POINTER: {
18618  stridx = DUK_STRIDX_UC_POINTER;
18619  break;
18620  }
18621  case DUK_TAG_LIGHTFUNC: {
18622  stridx = DUK_STRIDX_UC_FUNCTION;
18623  break;
18624  }
18625  case DUK_TAG_STRING: {
18626  duk_hstring *h;
18627  h = DUK_TVAL_GET_STRING(tv);
18628  DUK_ASSERT(h != NULL);
18629  if (DUK_HSTRING_HAS_SYMBOL(h)) {
18630  stridx = DUK_STRIDX_UC_SYMBOL;
18631  } else {
18632  stridx = DUK_STRIDX_UC_STRING;
18633  }
18634  break;
18635  }
18636  case DUK_TAG_OBJECT: {
18637  duk_hobject *h;
18638  duk_small_uint_t classnum;
18639 
18640  h = DUK_TVAL_GET_OBJECT(tv);
18641  DUK_ASSERT(h != NULL);
18642  classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h);
18643  stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
18644 
18645  /* XXX: This is not entirely correct anymore; in ES2015 the
18646  * default lookup should use @@toStringTag to come up with
18647  * e.g. [object Symbol], [object Uint8Array], etc. See
18648  * ES2015 Section 19.1.3.6. The downside of implementing that
18649  * directly is that the @@toStringTag lookup may have side
18650  * effects, so all call sites must be checked for that.
18651  * Some may need a side-effect free lookup, e.g. avoiding
18652  * getters which are not typical.
18653  */
18654  break;
18655  }
18656  case DUK_TAG_BUFFER: {
18657  stridx = DUK_STRIDX_UINT8_ARRAY;
18658  break;
18659  }
18660 #if defined(DUK_USE_FASTINT)
18661  case DUK_TAG_FASTINT:
18662  /* Fall through to generic number case. */
18663 #endif
18664  default: {
18665  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* number (maybe fastint) */
18666  stridx = DUK_STRIDX_UC_NUMBER;
18667  break;
18668  }
18669  }
18670  h_strclass = DUK_HTHREAD_GET_STRING(thr, stridx);
18671  DUK_ASSERT(h_strclass != NULL);
18672 
18673  duk_push_sprintf(ctx, "[object %s]", (const char *) DUK_HSTRING_GET_DATA(h_strclass));
18674 }
18675 
18676 /* XXX: other variants like uint, u32 etc */
18677 DUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_context *ctx, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {
18678  duk_hthread *thr = (duk_hthread *) ctx;
18679  duk_tval *tv;
18680  duk_tval tv_tmp;
18681  duk_double_t d, dmin, dmax;
18682  duk_int_t res;
18683  duk_bool_t clamped = 0;
18684 
18685  DUK_ASSERT_CTX_VALID(ctx);
18686 
18687  tv = duk_require_tval(ctx, idx);
18688  DUK_ASSERT(tv != NULL);
18689  d = duk_js_tointeger(thr, tv); /* E5 Section 9.4, ToInteger() */
18690 
18691  dmin = (duk_double_t) minval;
18692  dmax = (duk_double_t) maxval;
18693 
18694  if (d < dmin) {
18695  clamped = 1;
18696  res = minval;
18697  d = dmin;
18698  } else if (d > dmax) {
18699  clamped = 1;
18700  res = maxval;
18701  d = dmax;
18702  } else {
18703  res = (duk_int_t) d;
18704  }
18705  DUK_UNREF(d); /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
18706  /* 'd' and 'res' agree here */
18707 
18708  /* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
18709  tv = duk_get_tval(ctx, idx);
18710  DUK_ASSERT(tv != NULL); /* not popped by side effect */
18711  DUK_TVAL_SET_TVAL(&tv_tmp, tv);
18712 #if defined(DUK_USE_FASTINT)
18713 #if (DUK_INT_MAX <= 0x7fffffffL)
18714  DUK_TVAL_SET_I32(tv, res);
18715 #else
18716  /* Clamping needed if duk_int_t is 64 bits. */
18717  if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
18718  DUK_TVAL_SET_FASTINT(tv, res);
18719  } else {
18720  DUK_TVAL_SET_NUMBER(tv, d);
18721  }
18722 #endif
18723 #else
18724  DUK_TVAL_SET_NUMBER(tv, d); /* no need to incref */
18725 #endif
18726  DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
18727 
18728  if (out_clamped) {
18729  *out_clamped = clamped;
18730  } else {
18731  /* coerced value is updated to value stack even when RangeError thrown */
18732  if (clamped) {
18733  DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
18734  }
18735  }
18736 
18737  return res;
18738 }
18739 
18740 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_context *ctx, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
18741  duk_bool_t dummy;
18742  return duk_to_int_clamped_raw(ctx, idx, minval, maxval, &dummy);
18743 }
18744 
18745 DUK_INTERNAL duk_int_t duk_to_int_check_range(duk_context *ctx, duk_idx_t idx, duk_int_t minval, duk_int_t maxval) {
18746  return duk_to_int_clamped_raw(ctx, idx, minval, maxval, NULL); /* out_clamped==NULL -> RangeError if outside range */
18747 }
18748 
18749 DUK_EXTERNAL const char *duk_to_string(duk_context *ctx, duk_idx_t idx) {
18750  duk_hthread *thr = (duk_hthread *) ctx;
18751  duk_tval *tv;
18752 
18753  DUK_ASSERT_CTX_VALID(ctx);
18754  DUK_UNREF(thr);
18755 
18756  idx = duk_require_normalize_index(ctx, idx);
18757  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
18758  DUK_ASSERT(tv != NULL);
18759 
18760  switch (DUK_TVAL_GET_TAG(tv)) {
18761  case DUK_TAG_UNDEFINED: {
18762  duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_UNDEFINED);
18763  break;
18764  }
18765  case DUK_TAG_NULL: {
18766  duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL);
18767  break;
18768  }
18769  case DUK_TAG_BOOLEAN: {
18770  if (DUK_TVAL_GET_BOOLEAN(tv)) {
18771  duk_push_hstring_stridx(ctx, DUK_STRIDX_TRUE);
18772  } else {
18773  duk_push_hstring_stridx(ctx, DUK_STRIDX_FALSE);
18774  }
18775  break;
18776  }
18777  case DUK_TAG_STRING: {
18778  /* Nop for actual strings, TypeError for Symbols.
18779  * Because various internals rely on ToString() coercion of
18780  * internal strings, -allow- (NOP) string coercion for hidden
18781  * symbols.
18782  */
18783 #if 1
18784  duk_hstring *h;
18785  h = DUK_TVAL_GET_STRING(tv);
18786  DUK_ASSERT(h != NULL);
18787  if (DUK_HSTRING_HAS_SYMBOL(h)) {
18788  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
18789  } else {
18790  goto skip_replace;
18791  }
18792 #else
18793  goto skip_replace;
18794 #endif
18795  }
18796  case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
18797  case DUK_TAG_OBJECT: {
18798  /* Plain buffers: go through ArrayBuffer.prototype.toString()
18799  * for coercion.
18800  *
18801  * Symbol objects: duk_to_primitive() results in a plain symbol
18802  * value, and duk_to_string() then causes a TypeError.
18803  */
18804  duk_to_primitive(ctx, idx, DUK_HINT_STRING);
18805  DUK_ASSERT(!duk_is_buffer(ctx, idx)); /* ToPrimitive() must guarantee */
18806  DUK_ASSERT(!duk_is_object(ctx, idx));
18807  return duk_to_string(ctx, idx); /* Note: recursive call */
18808  }
18809  case DUK_TAG_POINTER: {
18810  void *ptr = DUK_TVAL_GET_POINTER(tv);
18811  if (ptr != NULL) {
18812  duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) ptr);
18813  } else {
18814  /* Represent a null pointer as 'null' to be consistent with
18815  * the JX format variant. Native '%p' format for a NULL
18816  * pointer may be e.g. '(nil)'.
18817  */
18818  duk_push_hstring_stridx(ctx, DUK_STRIDX_LC_NULL);
18819  }
18820  break;
18821  }
18822  case DUK_TAG_LIGHTFUNC: {
18823  /* Should match Function.prototype.toString() */
18824  duk_push_lightfunc_tostring(ctx, tv);
18825  break;
18826  }
18827 #if defined(DUK_USE_FASTINT)
18828  case DUK_TAG_FASTINT:
18829 #endif
18830  default: {
18831  /* number */
18832  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
18833  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
18834  duk_push_tval(ctx, tv);
18835  duk_numconv_stringify(ctx,
18836  10 /*radix*/,
18837  0 /*precision:shortest*/,
18838  0 /*force_exponential*/);
18839  break;
18840  }
18841  }
18842 
18843  duk_replace(ctx, idx);
18844 
18845  skip_replace:
18846  DUK_ASSERT(duk_is_string(ctx, idx));
18847  return duk_require_string(ctx, idx);
18848 }
18849 
18850 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_context *ctx, duk_idx_t idx) {
18851  duk_hstring *ret;
18852  DUK_ASSERT_CTX_VALID(ctx);
18853  duk_to_string(ctx, idx);
18854  ret = duk_get_hstring(ctx, idx);
18855  DUK_ASSERT(ret != NULL);
18856  return ret;
18857 }
18858 
18859 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_context *ctx) {
18860  return duk_to_hstring(ctx, -1);
18861 }
18862 
18863 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_context *ctx, duk_idx_t idx) {
18864  duk_hstring *ret;
18865  DUK_ASSERT_CTX_VALID(ctx);
18866  ret = duk_get_hstring(ctx, idx);
18867  if (ret && DUK_HSTRING_HAS_SYMBOL(ret)) {
18868  return ret;
18869  }
18870  return duk_to_hstring(ctx, idx);
18871 }
18872 
18873 /* Convert a plain buffer or any buffer object into a string, using the buffer
18874  * bytes 1:1 in the internal string representation. For views the active byte
18875  * slice (not element slice interpreted as an initializer) is used. This is
18876  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
18877  * string with the same bytes as in the buffer but rather (usually)
18878  * '[object ArrayBuffer]'.
18879  */
18880 DUK_EXTERNAL const char *duk_buffer_to_string(duk_context *ctx, duk_idx_t idx) {
18881  void *ptr_src;
18882  duk_size_t len;
18883  const char *res;
18884 
18885  idx = duk_require_normalize_index(ctx, idx);
18886 
18887  ptr_src = duk_require_buffer_data(ctx, idx, &len);
18888  DUK_ASSERT(ptr_src != NULL || len == 0);
18889 
18890  res = duk_push_lstring(ctx, (const char *) ptr_src, len);
18891  duk_replace(ctx, idx);
18892  return res;
18893 }
18894 
18895 DUK_EXTERNAL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
18896  duk_hthread *thr = (duk_hthread *) ctx;
18897  duk_hbuffer *h_buf;
18898  const duk_uint8_t *src_data;
18899  duk_size_t src_size;
18900  duk_uint8_t *dst_data;
18901 
18902  DUK_ASSERT_CTX_VALID(ctx);
18903  DUK_UNREF(thr);
18904 
18905  idx = duk_require_normalize_index(ctx, idx);
18906 
18907  h_buf = duk_get_hbuffer(ctx, idx);
18908  if (h_buf != NULL) {
18909  /* Buffer is kept as is, with the fixed/dynamic nature of the
18910  * buffer only changed if requested. An external buffer
18911  * is converted into a non-external dynamic buffer in a
18912  * duk_to_dynamic_buffer() call.
18913  */
18914  duk_uint_t tmp;
18915  duk_uint8_t *tmp_ptr;
18916 
18917  tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
18918  src_data = (const duk_uint8_t *) tmp_ptr;
18919  src_size = DUK_HBUFFER_GET_SIZE(h_buf);
18920 
18921  tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
18922  if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
18923  mode == DUK_BUF_MODE_DONTCARE) {
18924  /* Note: src_data may be NULL if input is a zero-size
18925  * dynamic buffer.
18926  */
18927  dst_data = tmp_ptr;
18928  goto skip_copy;
18929  }
18930  } else {
18931  /* Non-buffer value is first ToString() coerced, then converted
18932  * to a buffer (fixed buffer is used unless a dynamic buffer is
18933  * explicitly requested). Symbols are rejected with a TypeError.
18934  * XXX: C API could maybe allow symbol-to-buffer coercion?
18935  */
18936  src_data = (const duk_uint8_t *) duk_to_lstring(ctx, idx, &src_size);
18937  }
18938 
18939  dst_data = (duk_uint8_t *) duk_push_buffer(ctx, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
18940  if (DUK_LIKELY(src_size > 0)) {
18941  /* When src_size == 0, src_data may be NULL (if source
18942  * buffer is dynamic), and dst_data may be NULL (if
18943  * target buffer is dynamic). Avoid zero-size memcpy()
18944  * with an invalid pointer.
18945  */
18946  DUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);
18947  }
18948  duk_replace(ctx, idx);
18949  skip_copy:
18950 
18951  if (out_size) {
18952  *out_size = src_size;
18953  }
18954  return dst_data;
18955 }
18956 
18957 DUK_EXTERNAL void *duk_to_pointer(duk_context *ctx, duk_idx_t idx) {
18958  duk_tval *tv;
18959  void *res;
18960 
18961  DUK_ASSERT_CTX_VALID(ctx);
18962 
18963  idx = duk_require_normalize_index(ctx, idx);
18964  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
18965  DUK_ASSERT(tv != NULL);
18966 
18967  switch (DUK_TVAL_GET_TAG(tv)) {
18968  case DUK_TAG_UNDEFINED:
18969  case DUK_TAG_NULL:
18970  case DUK_TAG_BOOLEAN:
18971  res = NULL;
18972  break;
18973  case DUK_TAG_POINTER:
18974  res = DUK_TVAL_GET_POINTER(tv);
18975  break;
18976  case DUK_TAG_STRING:
18977  case DUK_TAG_OBJECT:
18978  case DUK_TAG_BUFFER:
18979  /* Heap allocated: return heap pointer which is NOT useful
18980  * for the caller, except for debugging.
18981  */
18982  res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
18983  break;
18984  case DUK_TAG_LIGHTFUNC:
18985  /* Function pointers do not always cast correctly to void *
18986  * (depends on memory and segmentation model for instance),
18987  * so they coerce to NULL.
18988  */
18989  res = NULL;
18990  break;
18991 #if defined(DUK_USE_FASTINT)
18992  case DUK_TAG_FASTINT:
18993 #endif
18994  default:
18995  /* number */
18996  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
18997  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
18998  res = NULL;
18999  break;
19000  }
19001 
19002  duk_push_pointer(ctx, res);
19003  duk_replace(ctx, idx);
19004  return res;
19005 }
19006 
19007 DUK_LOCAL void duk__push_func_from_lightfunc(duk_context *ctx, duk_c_function func, duk_small_uint_t lf_flags) {
19008  duk_idx_t nargs;
19009  duk_uint_t flags = 0; /* shared flags for a subset of types */
19010  duk_small_uint_t lf_len;
19011  duk_hnatfunc *nf;
19012 
19013  nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
19014  if (nargs == DUK_LFUNC_NARGS_VARARGS) {
19015  nargs = (duk_idx_t) DUK_VARARGS;
19016  }
19017 
19018  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19019  DUK_HOBJECT_FLAG_CONSTRUCTABLE |
19020  DUK_HOBJECT_FLAG_NATFUNC |
19021  DUK_HOBJECT_FLAG_NEWENV |
19022  DUK_HOBJECT_FLAG_STRICT |
19023  DUK_HOBJECT_FLAG_NOTAIL |
19024  /* DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC: omitted here intentionally */
19025  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
19026  (void) duk__push_c_function_raw(ctx, func, nargs, flags);
19027 
19028  lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
19029  if ((duk_idx_t) lf_len != nargs) {
19030  /* Explicit length is only needed if it differs from 'nargs'. */
19031  duk_push_int(ctx, (duk_int_t) lf_len);
19032  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
19033  }
19034 
19035 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
19036  duk_push_lightfunc_name_raw(ctx, func, lf_flags);
19037  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
19038 #endif
19039 
19040  nf = duk_known_hnatfunc(ctx, -1);
19041  nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
19042 
19043  /* Enable DUKFUNC exotic behavior once properties are set up. */
19044  DUK_HOBJECT_SET_EXOTIC_DUKFUNC((duk_hobject *) nf);
19045 }
19046 
19047 DUK_EXTERNAL void duk_to_object(duk_context *ctx, duk_idx_t idx) {
19048  duk_hthread *thr = (duk_hthread *) ctx;
19049  duk_tval *tv;
19050  duk_uint_t flags = 0; /* shared flags for a subset of types */
19051  duk_small_int_t proto = 0;
19052 
19053  DUK_ASSERT_CTX_VALID(ctx);
19054 
19055  idx = duk_require_normalize_index(ctx, idx);
19056  tv = DUK_GET_TVAL_POSIDX(ctx, idx);
19057  DUK_ASSERT(tv != NULL);
19058 
19059  switch (DUK_TVAL_GET_TAG(tv)) {
19060 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19061  case DUK_TAG_BUFFER: /* With no bufferobject support, don't object coerce. */
19062 #endif
19063  case DUK_TAG_UNDEFINED:
19064  case DUK_TAG_NULL: {
19065  DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
19066  break;
19067  }
19068  case DUK_TAG_BOOLEAN: {
19069  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19070  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
19071  proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
19072  goto create_object;
19073  }
19074  case DUK_TAG_STRING: {
19075  duk_hstring *h;
19076  h = DUK_TVAL_GET_STRING(tv);
19077  DUK_ASSERT(h != NULL);
19078  if (DUK_HSTRING_HAS_SYMBOL(h)) {
19079  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19080  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
19081  proto = DUK_BIDX_SYMBOL_PROTOTYPE;
19082  } else {
19083  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19084  DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
19085  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
19086  proto = DUK_BIDX_STRING_PROTOTYPE;
19087  }
19088  goto create_object;
19089  }
19090  case DUK_TAG_OBJECT: {
19091  /* nop */
19092  break;
19093  }
19094 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19095  case DUK_TAG_BUFFER: {
19096  /* A plain buffer object coerces to a full ArrayBuffer which
19097  * is not fully transparent behavior (ToObject() should be a
19098  * nop for an object). This behavior matches lightfuncs which
19099  * also coerce to an equivalent Function object. There are
19100  * also downsides to defining ToObject(plainBuffer) as a no-op;
19101  * for example duk_to_hobject() could result in a NULL pointer.
19102  */
19103  duk_hbuffer *h_buf;
19104 
19105  h_buf = DUK_TVAL_GET_BUFFER(tv);
19106  DUK_ASSERT(h_buf != NULL);
19107  duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
19108  goto replace_value;
19109  }
19110 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
19111  case DUK_TAG_POINTER: {
19112  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19113  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
19114  proto = DUK_BIDX_POINTER_PROTOTYPE;
19115  goto create_object;
19116  }
19117  case DUK_TAG_LIGHTFUNC: {
19118  /* Lightfunc coerces to a Function instance with concrete
19119  * properties. Since 'length' is virtual for Duktape/C
19120  * functions, don't need to define that. The result is made
19121  * extensible to mimic what happens to strings in object
19122  * coercion:
19123  *
19124  * > Object.isExtensible(Object('foo'))
19125  * true
19126  */
19127  duk_small_uint_t lf_flags;
19128  duk_c_function func;
19129 
19130  DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
19131  duk__push_func_from_lightfunc(ctx, func, lf_flags);
19132  goto replace_value;
19133  }
19134 #if defined(DUK_USE_FASTINT)
19135  case DUK_TAG_FASTINT:
19136 #endif
19137  default: {
19138  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
19139  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
19140  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
19141  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
19142  proto = DUK_BIDX_NUMBER_PROTOTYPE;
19143  goto create_object;
19144  }
19145  }
19146  DUK_ASSERT(duk_is_object(ctx, idx));
19147  return;
19148 
19149  create_object:
19150  (void) duk_push_object_helper(ctx, flags, proto);
19151 
19152  /* Note: Boolean prototype's internal value property is not writable,
19153  * but duk_xdef_prop_stridx() disregards the write protection. Boolean
19154  * instances are immutable.
19155  *
19156  * String and buffer special behaviors are already enabled which is not
19157  * ideal, but a write to the internal value is not affected by them.
19158  */
19159  duk_dup(ctx, idx);
19160  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
19161 
19162  replace_value:
19163  duk_replace(ctx, idx);
19164  DUK_ASSERT(duk_is_object(ctx, idx));
19165 }
19166 
19167 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_context *ctx, duk_idx_t idx) {
19168  duk_hobject *ret;
19169  DUK_ASSERT_CTX_VALID(ctx);
19170  duk_to_object(ctx, idx);
19171  ret = duk_known_hobject(ctx, idx);
19172  return ret;
19173 }
19174 
19175 /*
19176  * Type checking
19177  */
19178 
19179 DUK_LOCAL duk_bool_t duk__tag_check(duk_context *ctx, duk_idx_t idx, duk_small_uint_t tag) {
19180  duk_tval *tv;
19181 
19182  tv = duk_get_tval_or_unused(ctx, idx);
19183  DUK_ASSERT(tv != NULL);
19184  return (DUK_TVAL_GET_TAG(tv) == tag);
19185 }
19186 
19187 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_context *ctx, duk_idx_t idx, duk_uint_t flag_mask) {
19188  duk_hobject *obj;
19189 
19190  DUK_ASSERT_CTX_VALID(ctx);
19191 
19192  obj = duk_get_hobject(ctx, idx);
19193  if (obj) {
19194  return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
19195  }
19196  return 0;
19197 }
19198 
19199 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
19200  DUK_ASSERT(tv != NULL);
19201 
19202 #if defined(DUK_USE_PACKED_TVAL)
19203  switch (DUK_TVAL_GET_TAG(tv)) {
19204  case DUK_TAG_UNUSED:
19205  return DUK_TYPE_NONE;
19206  case DUK_TAG_UNDEFINED:
19207  return DUK_TYPE_UNDEFINED;
19208  case DUK_TAG_NULL:
19209  return DUK_TYPE_NULL;
19210  case DUK_TAG_BOOLEAN:
19211  return DUK_TYPE_BOOLEAN;
19212  case DUK_TAG_STRING:
19213  return DUK_TYPE_STRING;
19214  case DUK_TAG_OBJECT:
19215  return DUK_TYPE_OBJECT;
19216  case DUK_TAG_BUFFER:
19217  return DUK_TYPE_BUFFER;
19218  case DUK_TAG_POINTER:
19219  return DUK_TYPE_POINTER;
19220  case DUK_TAG_LIGHTFUNC:
19221  return DUK_TYPE_LIGHTFUNC;
19222 #if defined(DUK_USE_FASTINT)
19223  case DUK_TAG_FASTINT:
19224 #endif
19225  default:
19226  /* Note: number has no explicit tag (in 8-byte representation) */
19227  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
19228  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
19229  return DUK_TYPE_NUMBER;
19230  }
19231 #else /* DUK_USE_PACKED_TVAL */
19232  DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
19233  DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
19234  return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
19235 #endif /* DUK_USE_PACKED_TVAL */
19236 }
19237 
19238 DUK_EXTERNAL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t idx) {
19239  duk_tval *tv;
19240 
19241  DUK_ASSERT_CTX_VALID(ctx);
19242 
19243  tv = duk_get_tval_or_unused(ctx, idx);
19244  DUK_ASSERT(tv != NULL);
19245 
19246  return duk_get_type_tval(tv);
19247 }
19248 
19249 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
19250 DUK_LOCAL const char *duk__type_names[] = {
19251  "none",
19252  "undefined",
19253  "null",
19254  "boolean",
19255  "number",
19256  "string",
19257  "object",
19258  "buffer",
19259  "pointer",
19260  "lightfunc"
19261 };
19262 
19263 DUK_INTERNAL const char *duk_get_type_name(duk_context *ctx, duk_idx_t idx) {
19264  duk_int_t type_tag;
19265 
19266  type_tag = duk_get_type(ctx, idx);
19267  DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
19268  DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
19269 
19270  return duk__type_names[type_tag];
19271 }
19272 #endif
19273 
19274 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_context *ctx, duk_idx_t idx) {
19275  duk_tval *tv;
19276  duk_hobject *obj;
19277 
19278  tv = duk_get_tval_or_unused(ctx, idx);
19279  DUK_ASSERT(tv != NULL);
19280 
19281  switch (DUK_TVAL_GET_TAG(tv)) {
19282  case DUK_TAG_OBJECT:
19283  obj = DUK_TVAL_GET_OBJECT(tv);
19284  DUK_ASSERT(obj != NULL);
19285  return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
19286  case DUK_TAG_BUFFER:
19287  /* Buffers behave like Uint8Array objects. */
19288  return DUK_HOBJECT_CLASS_UINT8ARRAY;
19289  case DUK_TAG_LIGHTFUNC:
19290  /* Lightfuncs behave like Function objects. */
19291  return DUK_HOBJECT_CLASS_FUNCTION;
19292  default:
19293  /* Primitive or UNUSED, no class number. */
19294  return DUK_HOBJECT_CLASS_NONE;
19295  }
19296 }
19297 
19298 DUK_EXTERNAL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t idx, duk_int_t type) {
19299  DUK_ASSERT_CTX_VALID(ctx);
19300 
19301  return (duk_get_type(ctx, idx) == type) ? 1 : 0;
19302 }
19303 
19304 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
19305  DUK_ASSERT(tv != NULL);
19306 
19307 #if defined(DUK_USE_PACKED_TVAL)
19308  switch (DUK_TVAL_GET_TAG(tv)) {
19309  case DUK_TAG_UNUSED:
19310  return DUK_TYPE_MASK_NONE;
19311  case DUK_TAG_UNDEFINED:
19312  return DUK_TYPE_MASK_UNDEFINED;
19313  case DUK_TAG_NULL:
19314  return DUK_TYPE_MASK_NULL;
19315  case DUK_TAG_BOOLEAN:
19316  return DUK_TYPE_MASK_BOOLEAN;
19317  case DUK_TAG_STRING:
19318  return DUK_TYPE_MASK_STRING;
19319  case DUK_TAG_OBJECT:
19320  return DUK_TYPE_MASK_OBJECT;
19321  case DUK_TAG_BUFFER:
19322  return DUK_TYPE_MASK_BUFFER;
19323  case DUK_TAG_POINTER:
19324  return DUK_TYPE_MASK_POINTER;
19325  case DUK_TAG_LIGHTFUNC:
19326  return DUK_TYPE_MASK_LIGHTFUNC;
19327 #if defined(DUK_USE_FASTINT)
19328  case DUK_TAG_FASTINT:
19329 #endif
19330  default:
19331  /* Note: number has no explicit tag (in 8-byte representation) */
19332  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
19333  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
19334  return DUK_TYPE_MASK_NUMBER;
19335  }
19336 #else /* DUK_USE_PACKED_TVAL */
19337  DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
19338  DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
19339  return (duk_int_t) duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
19340 #endif /* DUK_USE_PACKED_TVAL */
19341 }
19342 
19343 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t idx) {
19344  duk_tval *tv;
19345 
19346  DUK_ASSERT_CTX_VALID(ctx);
19347 
19348  tv = duk_get_tval_or_unused(ctx, idx);
19349  DUK_ASSERT(tv != NULL);
19350 
19351  return duk_get_type_mask_tval(tv);
19352 }
19353 
19354 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t mask) {
19355  duk_hthread *thr = (duk_hthread *) ctx;
19356 
19357  DUK_ASSERT_CTX_VALID(ctx);
19358 
19359  if (duk_get_type_mask(ctx, idx) & mask) {
19360  return 1;
19361  }
19362  if (mask & DUK_TYPE_MASK_THROW) {
19363  DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
19364  DUK_UNREACHABLE();
19365  }
19366  return 0;
19367 }
19368 
19369 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t idx) {
19370  DUK_ASSERT_CTX_VALID(ctx);
19371  return duk__tag_check(ctx, idx, DUK_TAG_UNDEFINED);
19372 }
19373 
19374 DUK_EXTERNAL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t idx) {
19375  DUK_ASSERT_CTX_VALID(ctx);
19376  return duk__tag_check(ctx, idx, DUK_TAG_NULL);
19377 }
19378 
19379 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t idx) {
19380  DUK_ASSERT_CTX_VALID(ctx);
19381  return duk__tag_check(ctx, idx, DUK_TAG_BOOLEAN);
19382 }
19383 
19384 DUK_EXTERNAL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t idx) {
19385  duk_tval *tv;
19386 
19387  DUK_ASSERT_CTX_VALID(ctx);
19388 
19389  /*
19390  * Number is special because it doesn't have a specific
19391  * tag in the 8-byte representation.
19392  */
19393 
19394  /* XXX: shorter version for unpacked representation? */
19395 
19396  tv = duk_get_tval_or_unused(ctx, idx);
19397  DUK_ASSERT(tv != NULL);
19398  return DUK_TVAL_IS_NUMBER(tv);
19399 }
19400 
19401 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t idx) {
19402  /* XXX: This will now return false for non-numbers, even though they would
19403  * coerce to NaN (as a general rule). In particular, duk_get_number()
19404  * returns a NaN for non-numbers, so should this function also return
19405  * true for non-numbers?
19406  */
19407 
19408  duk_tval *tv;
19409 
19410  DUK_ASSERT_CTX_VALID(ctx);
19411 
19412  tv = duk_get_tval_or_unused(ctx, idx);
19413  DUK_ASSERT(tv != NULL);
19414 
19415  /* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
19416  if (!DUK_TVAL_IS_NUMBER(tv)) {
19417  return 0;
19418  }
19419  return DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
19420 }
19421 
19422 DUK_EXTERNAL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t idx) {
19423  DUK_ASSERT_CTX_VALID(ctx);
19424  return duk__tag_check(ctx, idx, DUK_TAG_STRING);
19425 }
19426 
19427 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_context *ctx, duk_idx_t idx) {
19428  DUK_ASSERT_CTX_VALID(ctx);
19429  return duk_get_hstring_notsymbol(ctx, idx) != NULL;
19430 }
19431 
19432 DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t idx) {
19433  DUK_ASSERT_CTX_VALID(ctx);
19434  return duk__tag_check(ctx, idx, DUK_TAG_OBJECT);
19435 }
19436 
19437 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t idx) {
19438  DUK_ASSERT_CTX_VALID(ctx);
19439  return duk__tag_check(ctx, idx, DUK_TAG_BUFFER);
19440 }
19441 
19442 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19443 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx) {
19444  duk_tval *tv;
19445 
19446  DUK_ASSERT_CTX_VALID(ctx);
19447 
19448  tv = duk_get_tval_or_unused(ctx, idx);
19449  DUK_ASSERT(tv != NULL);
19450  if (DUK_TVAL_IS_BUFFER(tv)) {
19451  return 1;
19452  } else if (DUK_TVAL_IS_OBJECT(tv)) {
19453  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
19454  DUK_ASSERT(h != NULL);
19455  if (DUK_HOBJECT_IS_BUFOBJ(h)) {
19456  return 1;
19457  }
19458  }
19459  return 0;
19460 }
19461 #else /* DUK_USE_BUFFEROBJECT_SUPPORT */
19462 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx) {
19463  DUK_ASSERT_CTX_VALID(ctx);
19464 
19465  return duk_is_buffer(ctx, idx);
19466 }
19467 
19468 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
19469 
19470 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t idx) {
19471  DUK_ASSERT_CTX_VALID(ctx);
19472  return duk__tag_check(ctx, idx, DUK_TAG_POINTER);
19473 }
19474 
19475 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t idx) {
19476  DUK_ASSERT_CTX_VALID(ctx);
19477  return duk__tag_check(ctx, idx, DUK_TAG_LIGHTFUNC);
19478 }
19479 
19480 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_context *ctx, duk_idx_t idx) {
19481  duk_hstring *h;
19482 
19483  DUK_ASSERT_CTX_VALID(ctx);
19484  h = duk_get_hstring(ctx, idx);
19485  if (h != NULL && DUK_HSTRING_HAS_SYMBOL(h)) {
19486  return 1;
19487  }
19488  return 0;
19489 }
19490 
19491 DUK_EXTERNAL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t idx) {
19492  duk_hobject *obj;
19493 
19494  DUK_ASSERT_CTX_VALID(ctx);
19495 
19496  obj = duk_get_hobject(ctx, idx);
19497  if (obj) {
19498  return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
19499  }
19500  return 0;
19501 }
19502 
19503 DUK_EXTERNAL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t idx) {
19504  duk_tval *tv;
19505 
19506  DUK_ASSERT_CTX_VALID(ctx);
19507 
19508  tv = duk_get_tval_or_unused(ctx, idx);
19509  if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
19510  return 1;
19511  }
19512  return duk__obj_flag_any_default_false(ctx,
19513  idx,
19514  DUK_HOBJECT_FLAG_COMPFUNC |
19515  DUK_HOBJECT_FLAG_NATFUNC |
19516  DUK_HOBJECT_FLAG_BOUNDFUNC);
19517 }
19518 
19519 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t idx) {
19520  DUK_ASSERT_CTX_VALID(ctx);
19521  return duk__obj_flag_any_default_false(ctx,
19522  idx,
19523  DUK_HOBJECT_FLAG_NATFUNC);
19524 }
19525 
19526 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t idx) {
19527  DUK_ASSERT_CTX_VALID(ctx);
19528  return duk__obj_flag_any_default_false(ctx,
19529  idx,
19530  DUK_HOBJECT_FLAG_COMPFUNC);
19531 }
19532 
19533 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t idx) {
19534  DUK_ASSERT_CTX_VALID(ctx);
19535  return duk__obj_flag_any_default_false(ctx,
19536  idx,
19537  DUK_HOBJECT_FLAG_BOUNDFUNC);
19538 }
19539 
19540 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t idx) {
19541  DUK_ASSERT_CTX_VALID(ctx);
19542  return duk__obj_flag_any_default_false(ctx,
19543  idx,
19544  DUK_HOBJECT_FLAG_THREAD);
19545 }
19546 
19547 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t idx) {
19548  duk_tval *tv;
19549 
19550  DUK_ASSERT_CTX_VALID(ctx);
19551 
19552  tv = duk_get_tval_or_unused(ctx, idx);
19553  DUK_ASSERT(tv != NULL);
19554  if (DUK_TVAL_IS_BUFFER(tv)) {
19555  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19556  DUK_ASSERT(h != NULL);
19557  return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
19558  }
19559  return 0;
19560 }
19561 
19562 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t idx) {
19563  duk_tval *tv;
19564 
19565  DUK_ASSERT_CTX_VALID(ctx);
19566 
19567  tv = duk_get_tval_or_unused(ctx, idx);
19568  DUK_ASSERT(tv != NULL);
19569  if (DUK_TVAL_IS_BUFFER(tv)) {
19570  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19571  DUK_ASSERT(h != NULL);
19572  return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
19573  }
19574  return 0;
19575 }
19576 
19577 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t idx) {
19578  duk_tval *tv;
19579 
19580  DUK_ASSERT_CTX_VALID(ctx);
19581 
19582  tv = duk_get_tval_or_unused(ctx, idx);
19583  DUK_ASSERT(tv != NULL);
19584  if (DUK_TVAL_IS_BUFFER(tv)) {
19585  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19586  DUK_ASSERT(h != NULL);
19587  return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
19588  }
19589  return 0;
19590 }
19591 
19592 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t idx) {
19593  duk_hthread *thr = (duk_hthread *) ctx;
19594  duk_hobject *h;
19595  duk_uint_t sanity;
19596 
19597  DUK_ASSERT_CTX_VALID(ctx);
19598 
19599  h = duk_get_hobject(ctx, idx);
19600 
19601  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
19602  do {
19603  if (!h) {
19604  return DUK_ERR_NONE;
19605  }
19606  if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
19607  return DUK_ERR_EVAL_ERROR;
19608  }
19609  if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
19610  return DUK_ERR_RANGE_ERROR;
19611  }
19612  if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
19613  return DUK_ERR_REFERENCE_ERROR;
19614  }
19615  if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
19616  return DUK_ERR_SYNTAX_ERROR;
19617  }
19618  if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
19619  return DUK_ERR_TYPE_ERROR;
19620  }
19621  if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
19622  return DUK_ERR_URI_ERROR;
19623  }
19624  if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
19625  return DUK_ERR_ERROR;
19626  }
19627 
19628  h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
19629  } while (--sanity > 0);
19630 
19631  return DUK_ERR_NONE;
19632 }
19633 
19634 /*
19635  * Pushers
19636  */
19637 
19638 DUK_INTERNAL void duk_push_tval(duk_context *ctx, duk_tval *tv) {
19639  duk_hthread *thr;
19640  duk_tval *tv_slot;
19641 
19642  DUK_ASSERT_CTX_VALID(ctx);
19643  DUK_ASSERT(tv != NULL);
19644  thr = (duk_hthread *) ctx;
19645  DUK__CHECK_SPACE();
19646  tv_slot = thr->valstack_top++;
19647  DUK_TVAL_SET_TVAL(tv_slot, tv);
19648  DUK_TVAL_INCREF(thr, tv); /* no side effects */
19649 }
19650 
19651 DUK_EXTERNAL void duk_push_undefined(duk_context *ctx) {
19652  duk_hthread *thr;
19653 
19654  DUK_ASSERT_CTX_VALID(ctx);
19655  thr = (duk_hthread *) ctx;
19656  DUK__CHECK_SPACE();
19657 
19658  /* Because value stack init policy is 'undefined above top',
19659  * we don't need to write, just assert.
19660  */
19661  thr->valstack_top++;
19662  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
19663 }
19664 
19665 DUK_EXTERNAL void duk_push_null(duk_context *ctx) {
19666  duk_hthread *thr;
19667  duk_tval *tv_slot;
19668 
19669  DUK_ASSERT_CTX_VALID(ctx);
19670  thr = (duk_hthread *) ctx;
19671  DUK__CHECK_SPACE();
19672  tv_slot = thr->valstack_top++;
19673  DUK_TVAL_SET_NULL(tv_slot);
19674 }
19675 
19676 DUK_EXTERNAL void duk_push_boolean(duk_context *ctx, duk_bool_t val) {
19677  duk_hthread *thr;
19678  duk_tval *tv_slot;
19679  duk_small_int_t b;
19680 
19681  DUK_ASSERT_CTX_VALID(ctx);
19682  thr = (duk_hthread *) ctx;
19683  DUK__CHECK_SPACE();
19684  b = (val ? 1 : 0); /* ensure value is 1 or 0 (not other non-zero) */
19685  tv_slot = thr->valstack_top++;
19686  DUK_TVAL_SET_BOOLEAN(tv_slot, b);
19687 }
19688 
19689 DUK_EXTERNAL void duk_push_true(duk_context *ctx) {
19690  duk_hthread *thr;
19691  duk_tval *tv_slot;
19692 
19693  DUK_ASSERT_CTX_VALID(ctx);
19694  thr = (duk_hthread *) ctx;
19695  DUK__CHECK_SPACE();
19696  tv_slot = thr->valstack_top++;
19697  DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
19698 }
19699 
19700 DUK_EXTERNAL void duk_push_false(duk_context *ctx) {
19701  duk_hthread *thr;
19702  duk_tval *tv_slot;
19703 
19704  DUK_ASSERT_CTX_VALID(ctx);
19705  thr = (duk_hthread *) ctx;
19706  DUK__CHECK_SPACE();
19707  tv_slot = thr->valstack_top++;
19708  DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
19709 }
19710 
19711 /* normalize NaN which may not match our canonical internal NaN */
19712 DUK_EXTERNAL void duk_push_number(duk_context *ctx, duk_double_t val) {
19713  duk_hthread *thr;
19714  duk_tval *tv_slot;
19715  duk_double_union du;
19716 
19717  DUK_ASSERT_CTX_VALID(ctx);
19718  thr = (duk_hthread *) ctx;
19719  DUK__CHECK_SPACE();
19720  du.d = val;
19721  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
19722  tv_slot = thr->valstack_top++;
19723  DUK_TVAL_SET_NUMBER(tv_slot, du.d);
19724 }
19725 
19726 DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val) {
19727 #if defined(DUK_USE_FASTINT)
19728  duk_hthread *thr;
19729  duk_tval *tv_slot;
19730 
19731  DUK_ASSERT_CTX_VALID(ctx);
19732  thr = (duk_hthread *) ctx;
19733  DUK__CHECK_SPACE();
19734  tv_slot = thr->valstack_top++;
19735 #if DUK_INT_MAX <= 0x7fffffffL
19736  DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
19737 #else
19738  if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
19739  DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
19740  } else {
19741  duk_double_t = (duk_double_t) val;
19742  DUK_TVAL_SET_NUMBER(tv_slot, d);
19743  }
19744 #endif
19745 #else /* DUK_USE_FASTINT */
19746  duk_hthread *thr;
19747  duk_tval *tv_slot;
19748  duk_double_t d;
19749 
19750  DUK_ASSERT_CTX_VALID(ctx);
19751  thr = (duk_hthread *) ctx;
19752  DUK__CHECK_SPACE();
19753  d = (duk_double_t) val;
19754  tv_slot = thr->valstack_top++;
19755  DUK_TVAL_SET_NUMBER(tv_slot, d);
19756 #endif /* DUK_USE_FASTINT */
19757 }
19758 
19759 DUK_EXTERNAL void duk_push_uint(duk_context *ctx, duk_uint_t val) {
19760 #if defined(DUK_USE_FASTINT)
19761  duk_hthread *thr;
19762  duk_tval *tv_slot;
19763 
19764  DUK_ASSERT_CTX_VALID(ctx);
19765  thr = (duk_hthread *) ctx;
19766  DUK__CHECK_SPACE();
19767  tv_slot = thr->valstack_top++;
19768 #if DUK_UINT_MAX <= 0xffffffffUL
19769  DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
19770 #else
19771  if (val <= DUK_FASTINT_MAX) { /* val is unsigned so >= 0 */
19772  /* XXX: take advantage of val being unsigned, no need to mask */
19773  DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
19774  } else {
19775  duk_double_t = (duk_double_t) val;
19776  DUK_TVAL_SET_NUMBER(tv_slot, d);
19777  }
19778 #endif
19779 #else /* DUK_USE_FASTINT */
19780  duk_hthread *thr;
19781  duk_tval *tv_slot;
19782  duk_double_t d;
19783 
19784  DUK_ASSERT_CTX_VALID(ctx);
19785  thr = (duk_hthread *) ctx;
19786  DUK__CHECK_SPACE();
19787  d = (duk_double_t) val;
19788  tv_slot = thr->valstack_top++;
19789  DUK_TVAL_SET_NUMBER(tv_slot, d);
19790 #endif /* DUK_USE_FASTINT */
19791 }
19792 
19793 DUK_EXTERNAL void duk_push_nan(duk_context *ctx) {
19794  duk_hthread *thr;
19795  duk_tval *tv_slot;
19796  duk_double_union du;
19797 
19798  DUK_ASSERT_CTX_VALID(ctx);
19799  thr = (duk_hthread *) ctx;
19800  DUK__CHECK_SPACE();
19801  DUK_DBLUNION_SET_NAN(&du);
19802  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
19803  tv_slot = thr->valstack_top++;
19804  DUK_TVAL_SET_NUMBER(tv_slot, du.d);
19805 }
19806 
19807 DUK_EXTERNAL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len) {
19808  duk_hthread *thr = (duk_hthread *) ctx;
19809  duk_hstring *h;
19810  duk_tval *tv_slot;
19811 
19812  DUK_ASSERT_CTX_VALID(ctx);
19813 
19814  /* check stack before interning (avoid hanging temp) */
19815  if (thr->valstack_top >= thr->valstack_end) {
19816  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
19817  }
19818 
19819  /* NULL with zero length represents an empty string; NULL with higher
19820  * length is also now trated like an empty string although it is
19821  * a bit dubious. This is unlike duk_push_string() which pushes a
19822  * 'null' if the input string is a NULL.
19823  */
19824  if (!str) {
19825  len = 0;
19826  }
19827 
19828  /* Check for maximum string length */
19829  if (len > DUK_HSTRING_MAX_BYTELEN) {
19830  DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
19831  }
19832 
19833  h = duk_heap_string_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
19834  DUK_ASSERT(h != NULL);
19835 
19836  tv_slot = thr->valstack_top++;
19837  DUK_TVAL_SET_STRING(tv_slot, h);
19838  DUK_HSTRING_INCREF(thr, h); /* no side effects */
19839 
19840  return (const char *) DUK_HSTRING_GET_DATA(h);
19841 }
19842 
19843 DUK_EXTERNAL const char *duk_push_string(duk_context *ctx, const char *str) {
19844  DUK_ASSERT_CTX_VALID(ctx);
19845 
19846  if (str) {
19847  return duk_push_lstring(ctx, str, DUK_STRLEN(str));
19848  } else {
19849  duk_push_null(ctx);
19850  return NULL;
19851  }
19852 }
19853 
19854 DUK_EXTERNAL void duk_push_pointer(duk_context *ctx, void *val) {
19855  duk_hthread *thr;
19856  duk_tval *tv_slot;
19857 
19858  DUK_ASSERT_CTX_VALID(ctx);
19859  thr = (duk_hthread *) ctx;
19860  DUK__CHECK_SPACE();
19861  tv_slot = thr->valstack_top++;
19862  DUK_TVAL_SET_POINTER(tv_slot, val);
19863 }
19864 
19865 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_context *ctx, duk_uint_t i) {
19866  duk_hstring *h_tmp;
19867 
19868  /* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
19869  duk_push_uint(ctx, (duk_uint_t) i);
19870  h_tmp = duk_to_hstring_m1(ctx);
19871  DUK_ASSERT(h_tmp != NULL);
19872  return h_tmp;
19873 }
19874 
19875 DUK_LOCAL void duk__push_this_helper(duk_context *ctx, duk_small_uint_t check_object_coercible) {
19876  duk_hthread *thr;
19877  duk_tval *tv_slot;
19878 
19879  DUK_ASSERT_CTX_VALID(ctx);
19880  DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
19881  thr = (duk_hthread *) ctx;
19882  DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
19883  DUK__CHECK_SPACE();
19884 
19885  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* because of valstack init policy */
19886  tv_slot = thr->valstack_top++;
19887 
19888  if (DUK_UNLIKELY(thr->callstack_top == 0)) {
19889  if (check_object_coercible) {
19890  goto type_error;
19891  }
19892  /* 'undefined' already on stack top */
19893  } else {
19894  duk_tval *tv;
19895 
19896  /* 'this' binding is just before current activation's bottom */
19897  DUK_ASSERT(thr->valstack_bottom > thr->valstack);
19898  tv = thr->valstack_bottom - 1;
19899  if (check_object_coercible &&
19900  (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
19901  /* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
19902  goto type_error;
19903  }
19904 
19905  DUK_TVAL_SET_TVAL(tv_slot, tv);
19906  DUK_TVAL_INCREF(thr, tv);
19907  }
19908  return;
19909 
19910  type_error:
19911  DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
19912 }
19913 
19914 DUK_EXTERNAL void duk_push_this(duk_context *ctx) {
19915  DUK_ASSERT_CTX_VALID(ctx);
19916 
19917  duk__push_this_helper(ctx, 0 /*check_object_coercible*/);
19918 }
19919 
19920 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_context *ctx) {
19921  DUK_ASSERT_CTX_VALID(ctx);
19922 
19923  duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
19924 }
19925 
19926 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_context *ctx) {
19927  duk_hobject *h;
19928 
19929  DUK_ASSERT_CTX_VALID(ctx);
19930 
19931  duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
19932  h = duk_to_hobject(ctx, -1);
19933  DUK_ASSERT(h != NULL);
19934  return h;
19935 }
19936 
19937 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_context *ctx) {
19938  DUK_ASSERT_CTX_VALID(ctx);
19939 
19940  duk__push_this_helper(ctx, 1 /*check_object_coercible*/);
19941  return duk_to_hstring_m1(ctx); /* This will reject all Symbol values; accepts Symbol objects. */
19942 }
19943 
19944 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_context *ctx) {
19945  duk_hthread *thr;
19946 
19947  DUK_ASSERT(ctx != NULL);
19948  thr = (duk_hthread *) ctx;
19949 
19950  DUK_ASSERT(thr->callstack_top > 0); /* caller required to know */
19951  DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* consequence of above */
19952  DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack); /* 'this' binding exists */
19953 
19954  return thr->valstack_bottom - 1;
19955 }
19956 
19957 DUK_EXTERNAL void duk_push_current_function(duk_context *ctx) {
19958  duk_hthread *thr = (duk_hthread *) ctx;
19959  duk_activation *act;
19960 
19961  DUK_ASSERT_CTX_VALID(ctx);
19962  DUK_ASSERT(thr != NULL);
19963  DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
19964  DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
19965 
19966  act = duk_hthread_get_current_activation(thr);
19967  if (act) {
19968  duk_push_tval(ctx, &act->tv_func);
19969  } else {
19970  duk_push_undefined(ctx);
19971  }
19972 }
19973 
19974 DUK_EXTERNAL void duk_push_current_thread(duk_context *ctx) {
19975  duk_hthread *thr = (duk_hthread *) ctx;
19976 
19977  DUK_ASSERT_CTX_VALID(ctx);
19978  DUK_ASSERT(thr != NULL);
19979 
19980  if (thr->heap->curr_thread) {
19981  duk_push_hobject(ctx, (duk_hobject *) thr->heap->curr_thread);
19982  } else {
19983  duk_push_undefined(ctx);
19984  }
19985 }
19986 
19987 DUK_EXTERNAL void duk_push_global_object(duk_context *ctx) {
19988  DUK_ASSERT_CTX_VALID(ctx);
19989 
19990  duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL);
19991 }
19992 
19993 /* XXX: size optimize */
19994 DUK_LOCAL void duk__push_stash(duk_context *ctx) {
19995  DUK_ASSERT_CTX_VALID(ctx);
19996  if (!duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE)) {
19997  DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
19998  duk_pop(ctx);
19999  duk_push_bare_object(ctx);
20000  duk_dup_top(ctx);
20001  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C); /* [ ... parent stash stash ] -> [ ... parent stash ] */
20002  }
20003  duk_remove_m2(ctx);
20004 }
20005 
20006 DUK_EXTERNAL void duk_push_heap_stash(duk_context *ctx) {
20007  duk_hthread *thr = (duk_hthread *) ctx;
20008  duk_heap *heap;
20009  DUK_ASSERT_CTX_VALID(ctx);
20010  heap = thr->heap;
20011  DUK_ASSERT(heap->heap_object != NULL);
20012  duk_push_hobject(ctx, heap->heap_object);
20013  duk__push_stash(ctx);
20014 }
20015 
20016 DUK_EXTERNAL void duk_push_global_stash(duk_context *ctx) {
20017  DUK_ASSERT_CTX_VALID(ctx);
20018  duk_push_global_object(ctx);
20019  duk__push_stash(ctx);
20020 }
20021 
20022 DUK_EXTERNAL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx) {
20023  duk_hthread *thr = (duk_hthread *) ctx;
20024  DUK_ASSERT_CTX_VALID(ctx);
20025  if (!target_ctx) {
20026  DUK_ERROR_TYPE_INVALID_ARGS(thr);
20027  return; /* not reached */
20028  }
20029  duk_push_hobject(ctx, (duk_hobject *) target_ctx);
20030  duk__push_stash(ctx);
20031 }
20032 
20033 /* XXX: duk_ssize_t would be useful here */
20034 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_context *ctx, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
20035  duk_int_t len;
20036 
20037  DUK_ASSERT_CTX_VALID(ctx);
20038  DUK_UNREF(ctx);
20039 
20040  /* NUL terminator handling doesn't matter here */
20041  len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
20042  if (len < (duk_int_t) sz) {
20043  /* Return value of 'sz' or more indicates output was (potentially)
20044  * truncated.
20045  */
20046  return (duk_int_t) len;
20047  }
20048  return -1;
20049 }
20050 
20051 DUK_EXTERNAL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap) {
20052  duk_hthread *thr = (duk_hthread *) ctx;
20053  duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
20054  duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
20055  duk_bool_t pushed_buf = 0;
20056  void *buf;
20057  duk_int_t len; /* XXX: duk_ssize_t */
20058  const char *res;
20059 
20060  DUK_ASSERT_CTX_VALID(ctx);
20061 
20062  /* special handling of fmt==NULL */
20063  if (!fmt) {
20064  duk_hstring *h_str;
20065  duk_push_hstring_empty(ctx);
20066  h_str = duk_known_hstring(ctx, -1);
20067  return (const char *) DUK_HSTRING_GET_DATA(h_str);
20068  }
20069 
20070  /* initial estimate based on format string */
20071  sz = DUK_STRLEN(fmt) + 16; /* format plus something to avoid just missing */
20072  if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
20073  sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
20074  }
20075  DUK_ASSERT(sz > 0);
20076 
20077  /* Try to make do with a stack buffer to avoid allocating a temporary buffer.
20078  * This works 99% of the time which is quite nice.
20079  */
20080  for (;;) {
20081  va_list ap_copy; /* copied so that 'ap' can be reused */
20082 
20083  if (sz <= sizeof(stack_buf)) {
20084  buf = stack_buf;
20085  } else if (!pushed_buf) {
20086  pushed_buf = 1;
20087  buf = duk_push_dynamic_buffer(ctx, sz);
20088  } else {
20089  buf = duk_resize_buffer(ctx, -1, sz);
20090  }
20091  DUK_ASSERT(buf != NULL);
20092 
20093  DUK_VA_COPY(ap_copy, ap);
20094  len = duk__try_push_vsprintf(ctx, buf, sz, fmt, ap_copy);
20095  va_end(ap_copy);
20096  if (len >= 0) {
20097  break;
20098  }
20099 
20100  /* failed, resize and try again */
20101  sz = sz * 2;
20102  if (sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT) {
20103  DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
20104  }
20105  }
20106 
20107  /* Cannot use duk_buffer_to_string() on the buffer because it is
20108  * usually larger than 'len'; 'buf' is also usually a stack buffer.
20109  */
20110  res = duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len); /* [ buf? res ] */
20111  if (pushed_buf) {
20112  duk_remove_m2(ctx);
20113  }
20114  return res;
20115 }
20116 
20117 DUK_EXTERNAL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...) {
20118  va_list ap;
20119  const char *ret;
20120 
20121  DUK_ASSERT_CTX_VALID(ctx);
20122 
20123  /* allow fmt==NULL */
20124  va_start(ap, fmt);
20125  ret = duk_push_vsprintf(ctx, fmt, ap);
20126  va_end(ap);
20127 
20128  return ret;
20129 }
20130 
20131 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
20132  duk_hthread *thr = (duk_hthread *) ctx;
20133  duk_tval *tv_slot;
20134  duk_hobject *h;
20135 
20136  DUK_ASSERT_CTX_VALID(ctx);
20137  DUK_ASSERT(prototype_bidx == -1 ||
20138  (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
20139 
20140  /* check stack first */
20141  if (thr->valstack_top >= thr->valstack_end) {
20142  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20143  }
20144 
20145  h = duk_hobject_alloc(thr->heap, hobject_flags_and_class);
20146  if (!h) {
20147  DUK_ERROR_ALLOC_FAILED(thr);
20148  }
20149 
20150  DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
20151 
20152  tv_slot = thr->valstack_top;
20153  DUK_TVAL_SET_OBJECT(tv_slot, h);
20154  DUK_HOBJECT_INCREF(thr, h); /* no side effects */
20155  thr->valstack_top++;
20156 
20157  /* object is now reachable */
20158 
20159  if (prototype_bidx >= 0) {
20160  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[prototype_bidx]);
20161  } else {
20162  DUK_ASSERT(prototype_bidx == -1);
20163  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
20164  }
20165 
20166  return h;
20167 }
20168 
20169 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
20170  duk_hthread *thr = (duk_hthread *) ctx;
20171  duk_hobject *h;
20172 
20173  DUK_ASSERT_CTX_VALID(ctx);
20174 
20175  h = duk_push_object_helper(ctx, hobject_flags_and_class, -1);
20176  DUK_ASSERT(h != NULL);
20177  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
20178  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, proto);
20179  return h;
20180 }
20181 
20182 DUK_EXTERNAL duk_idx_t duk_push_object(duk_context *ctx) {
20183  DUK_ASSERT_CTX_VALID(ctx);
20184 
20185  (void) duk_push_object_helper(ctx,
20186  DUK_HOBJECT_FLAG_EXTENSIBLE |
20187  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
20188  DUK_BIDX_OBJECT_PROTOTYPE);
20189  return duk_get_top_index_unsafe(ctx);
20190 }
20191 
20192 DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx) {
20193  duk_hthread *thr = (duk_hthread *) ctx;
20194  duk_uint_t flags;
20195  duk_harray *obj;
20196  duk_idx_t ret;
20197  duk_tval *tv_slot;
20198 
20199  DUK_ASSERT_CTX_VALID(ctx);
20200 
20201  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
20202  DUK_HOBJECT_FLAG_ARRAY_PART |
20203  DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
20204  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
20205 
20206  obj = duk_harray_alloc(thr->heap, flags);
20207  if (!obj) {
20208  DUK_ERROR_ALLOC_FAILED(thr);
20209  }
20210 
20211  /* XXX: since prototype is NULL, could save a check */
20212  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
20213 
20214  tv_slot = thr->valstack_top;
20215  DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
20216  DUK_HOBJECT_INCREF(thr, obj); /* XXX: could preallocate with refcount = 1 */
20217  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
20218  thr->valstack_top++;
20219 
20220  DUK_ASSERT(obj->length == 0); /* Array .length starts at zero. */
20221  return ret;
20222 }
20223 
20224 DUK_INTERNAL duk_harray *duk_push_harray(duk_context *ctx) {
20225  /* XXX: API call could do this directly, cast to void in API macro. */
20226  duk_hthread *thr;
20227  duk_harray *a;
20228 
20229  thr = (duk_hthread *) ctx;
20230  (void) duk_push_array(ctx);
20231  DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
20232  a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
20233  DUK_ASSERT(a != NULL);
20234  return a;
20235 }
20236 
20237 /* Push a duk_harray with preallocated size (.length also set to match size).
20238  * Caller may then populate array part of the duk_harray directly.
20239  */
20240 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_context *ctx, duk_uint32_t size) {
20241  duk_harray *a;
20242 
20243  a = duk_push_harray(ctx);
20244 
20245  duk_hobject_realloc_props((duk_hthread *) ctx,
20246  (duk_hobject *) a,
20247  0,
20248  size,
20249  0,
20250  0);
20251  a->length = size;
20252  return a;
20253 }
20254 
20255 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags) {
20256  duk_hthread *thr = (duk_hthread *) ctx;
20257  duk_hthread *obj;
20258  duk_idx_t ret;
20259  duk_tval *tv_slot;
20260 
20261  DUK_ASSERT_CTX_VALID(ctx);
20262 
20263  /* check stack first */
20264  if (thr->valstack_top >= thr->valstack_end) {
20265  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20266  }
20267 
20268  obj = duk_hthread_alloc(thr->heap,
20269  DUK_HOBJECT_FLAG_EXTENSIBLE |
20270  DUK_HOBJECT_FLAG_THREAD |
20271  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
20272  if (!obj) {
20273  DUK_ERROR_ALLOC_FAILED(thr);
20274  }
20275  obj->state = DUK_HTHREAD_STATE_INACTIVE;
20276 #if defined(DUK_USE_ROM_STRINGS)
20277  /* Nothing to initialize, strs[] is in ROM. */
20278 #else
20279 #if defined(DUK_USE_HEAPPTR16)
20280  obj->strs16 = thr->strs16;
20281 #else
20282  obj->strs = thr->strs;
20283 #endif
20284 #endif
20285  DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
20286 
20287  /* make the new thread reachable */
20288  tv_slot = thr->valstack_top;
20289  DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
20290  DUK_HTHREAD_INCREF(thr, obj);
20291  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
20292  thr->valstack_top++;
20293 
20294  /* important to do this *after* pushing, to make the thread reachable for gc */
20295  if (!duk_hthread_init_stacks(thr->heap, obj)) {
20296  DUK_ERROR_ALLOC_FAILED(thr);
20297  }
20298 
20299  /* initialize built-ins - either by copying or creating new ones */
20300  if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
20301  duk_hthread_create_builtin_objects(obj);
20302  } else {
20303  duk_hthread_copy_builtin_objects(thr, obj);
20304  }
20305 
20306  /* default prototype (Note: 'obj' must be reachable) */
20307  /* XXX: since prototype is NULL, could save a check */
20308  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
20309 
20310  /* Initial stack size satisfies the stack spare constraints so there
20311  * is no need to require stack here.
20312  */
20313  DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
20314  DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
20315 
20316  return ret;
20317 }
20318 
20319 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_context *ctx) {
20320  duk_hthread *thr = (duk_hthread *) ctx;
20321  duk_hcompfunc *obj;
20322  duk_tval *tv_slot;
20323 
20324  DUK_ASSERT_CTX_VALID(ctx);
20325 
20326  /* check stack first */
20327  if (thr->valstack_top >= thr->valstack_end) {
20328  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20329  }
20330 
20331  /* Template functions are not strictly constructable (they don't
20332  * have a "prototype" property for instance), so leave the
20333  * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
20334  */
20335 
20336  obj = duk_hcompfunc_alloc(thr->heap,
20337  DUK_HOBJECT_FLAG_EXTENSIBLE |
20338  DUK_HOBJECT_FLAG_COMPFUNC |
20339  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
20340  if (!obj) {
20341  DUK_ERROR_ALLOC_FAILED(thr);
20342  }
20343 
20344  DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
20345 
20346  tv_slot = thr->valstack_top;
20347  DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
20348  DUK_HOBJECT_INCREF(thr, obj);
20349  thr->valstack_top++;
20350 
20351  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
20352 
20353  return obj;
20354 }
20355 
20356 DUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_uint_t flags) {
20357  duk_hthread *thr = (duk_hthread *) ctx;
20358  duk_hnatfunc *obj;
20359  duk_idx_t ret;
20360  duk_tval *tv_slot;
20361  duk_int16_t func_nargs;
20362 
20363  DUK_ASSERT_CTX_VALID(ctx);
20364 
20365  /* check stack first */
20366  if (thr->valstack_top >= thr->valstack_end) {
20367  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20368  }
20369  if (func == NULL) {
20370  goto api_error;
20371  }
20372  if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
20373  func_nargs = (duk_int16_t) nargs;
20374  } else if (nargs == DUK_VARARGS) {
20375  func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
20376  } else {
20377  goto api_error;
20378  }
20379 
20380  obj = duk_hnatfunc_alloc(thr->heap, flags);
20381  if (!obj) {
20382  DUK_ERROR_ALLOC_FAILED(thr);
20383  }
20384 
20385  obj->func = func;
20386  obj->nargs = func_nargs;
20387 
20388  DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
20389  (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
20390 
20391  tv_slot = thr->valstack_top;
20392  DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
20393  DUK_HOBJECT_INCREF(thr, obj);
20394  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
20395  thr->valstack_top++;
20396 
20397  /* default prototype (Note: 'obj' must be reachable) */
20398  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
20399 
20400  return ret;
20401 
20402  api_error:
20403  DUK_ERROR_TYPE_INVALID_ARGS(thr);
20404  return 0; /* not reached */
20405 }
20406 
20407 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
20408  duk_uint_t flags;
20409 
20410  DUK_ASSERT_CTX_VALID(ctx);
20411 
20412  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
20413  DUK_HOBJECT_FLAG_CONSTRUCTABLE |
20414  DUK_HOBJECT_FLAG_NATFUNC |
20415  DUK_HOBJECT_FLAG_NEWENV |
20416  DUK_HOBJECT_FLAG_STRICT |
20417  DUK_HOBJECT_FLAG_NOTAIL |
20418  DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC |
20419  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
20420 
20421  return duk__push_c_function_raw(ctx, func, nargs, flags);
20422 }
20423 
20424 DUK_INTERNAL void duk_push_c_function_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
20425  duk_uint_t flags;
20426 
20427  DUK_ASSERT_CTX_VALID(ctx);
20428 
20429  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
20430  DUK_HOBJECT_FLAG_CONSTRUCTABLE |
20431  DUK_HOBJECT_FLAG_NATFUNC |
20432  DUK_HOBJECT_FLAG_NEWENV |
20433  DUK_HOBJECT_FLAG_STRICT |
20434  DUK_HOBJECT_FLAG_NOTAIL |
20435  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
20436 
20437  (void) duk__push_c_function_raw(ctx, func, nargs, flags);
20438 }
20439 
20440 DUK_INTERNAL void duk_push_c_function_noconstruct_noexotic(duk_context *ctx, duk_c_function func, duk_int_t nargs) {
20441  duk_uint_t flags;
20442 
20443  DUK_ASSERT_CTX_VALID(ctx);
20444 
20445  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
20446  DUK_HOBJECT_FLAG_NATFUNC |
20447  DUK_HOBJECT_FLAG_NEWENV |
20448  DUK_HOBJECT_FLAG_STRICT |
20449  DUK_HOBJECT_FLAG_NOTAIL |
20450  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
20451 
20452  (void) duk__push_c_function_raw(ctx, func, nargs, flags);
20453 }
20454 
20455 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) {
20456  duk_hthread *thr = (duk_hthread *) ctx;
20457  duk_tval tv_tmp;
20458  duk_small_uint_t lf_flags;
20459 
20460  DUK_ASSERT_CTX_VALID(ctx);
20461 
20462  /* check stack first */
20463  if (thr->valstack_top >= thr->valstack_end) {
20464  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20465  }
20466 
20467  if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
20468  /* as is */
20469  } else if (nargs == DUK_VARARGS) {
20470  nargs = DUK_LFUNC_NARGS_VARARGS;
20471  } else {
20472  goto api_error;
20473  }
20474  if (!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX)) {
20475  goto api_error;
20476  }
20477  if (!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX)) {
20478  goto api_error;
20479  }
20480 
20481  lf_flags = DUK_LFUNC_FLAGS_PACK(magic, length, nargs);
20482  DUK_TVAL_SET_LIGHTFUNC(&tv_tmp, func, lf_flags);
20483  duk_push_tval(ctx, &tv_tmp); /* XXX: direct valstack write */
20484  DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
20485  return ((duk_idx_t) (thr->valstack_top - thr->valstack_bottom)) - 1;
20486 
20487  api_error:
20488  DUK_ERROR_TYPE_INVALID_ARGS(thr);
20489  return 0; /* not reached */
20490 }
20491 
20492 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20493 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
20494  duk_hthread *thr = (duk_hthread *) ctx;
20495  duk_hbufobj *obj;
20496  duk_tval *tv_slot;
20497 
20498  DUK_ASSERT(ctx != NULL);
20499  DUK_ASSERT(prototype_bidx >= 0);
20500 
20501  /* check stack first */
20502  if (thr->valstack_top >= thr->valstack_end) {
20503  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20504  }
20505 
20506  obj = duk_hbufobj_alloc(thr->heap, hobject_flags_and_class);
20507  if (!obj) {
20508  DUK_ERROR_ALLOC_FAILED(thr);
20509  }
20510 
20511  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
20512  DUK_ASSERT_HBUFOBJ_VALID(obj);
20513 
20514  tv_slot = thr->valstack_top;
20515  DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
20516  DUK_HOBJECT_INCREF(thr, obj);
20517  thr->valstack_top++;
20518 
20519  return obj;
20520 }
20521 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
20522 
20523 /* XXX: There's quite a bit of overlap with buffer creation handling in
20524  * duk_bi_buffer.c. Look for overlap and refactor.
20525  */
20526 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20527 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
20528  (((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
20529 
20530 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
20531  /* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
20532  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER, DUK_BIDX_ARRAYBUFFER_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_ARRAYBUFFER */
20533  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_NODEJS_BUFFER */
20534  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW, DUK_BIDX_DATAVIEW_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 0), /* DUK_BUFOBJ_DATAVIEW */
20535  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY, DUK_BIDX_INT8ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT8, 0, 1), /* DUK_BUFOBJ_INT8ARRAY */
20536  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY, DUK_BIDX_UINT8ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8, 0, 1), /* DUK_BUFOBJ_UINT8ARRAY */
20537  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1), /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
20538  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY, DUK_BIDX_INT16ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT16, 1, 1), /* DUK_BUFOBJ_INT16ARRAY */
20539  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY, DUK_BIDX_UINT16ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT16, 1, 1), /* DUK_BUFOBJ_UINT16ARRAY */
20540  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY, DUK_BIDX_INT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_INT32, 2, 1), /* DUK_BUFOBJ_INT32ARRAY */
20541  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY, DUK_BIDX_UINT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT32, 2, 1), /* DUK_BUFOBJ_UINT32ARRAY */
20542  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY, DUK_BIDX_FLOAT32ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_FLOAT32, 2, 1), /* DUK_BUFOBJ_FLOAT32ARRAY */
20543  DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY, DUK_BIDX_FLOAT64ARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_FLOAT64, 3, 1) /* DUK_BUFOBJ_FLOAT64ARRAY */
20544 };
20545 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
20546 
20547 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20548 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) {
20549  duk_hthread *thr;
20550  duk_hbufobj *h_bufobj;
20551  duk_hbuffer *h_val;
20552  duk_uint32_t tmp;
20553  duk_uint_t classnum;
20554  duk_uint_t protobidx;
20555  duk_uint_t lookupidx;
20556  duk_uint_t uint_offset, uint_length, uint_added;
20557 
20558  DUK_ASSERT_CTX_VALID(ctx);
20559  thr = (duk_hthread *) ctx;
20560  DUK_UNREF(thr);
20561 
20562  /* The underlying types for offset/length in duk_hbufobj is
20563  * duk_uint_t; make sure argument values fit and that
20564  * offset + length does not wrap.
20565  */
20566  uint_offset = (duk_uint_t) byte_offset;
20567  uint_length = (duk_uint_t) byte_length;
20568  if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
20569  if ((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length) {
20570  goto range_error;
20571  }
20572  }
20573  uint_added = uint_offset + uint_length;
20574  if (uint_added < uint_offset) {
20575  goto range_error;
20576  }
20577  DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
20578 
20579  DUK_ASSERT_DISABLE(flags >= 0); /* flags is unsigned */
20580  lookupidx = flags & 0x0f; /* 4 low bits */
20581  if (lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t)) {
20582  goto arg_error;
20583  }
20584  tmp = duk__bufobj_flags_lookup[lookupidx];
20585  classnum = tmp >> 24;
20586  protobidx = (tmp >> 16) & 0xff;
20587 
20588  h_val = duk_require_hbuffer(ctx, idx_buffer);
20589  DUK_ASSERT(h_val != NULL);
20590 
20591  h_bufobj = duk_push_bufobj_raw(ctx,
20592  DUK_HOBJECT_FLAG_EXTENSIBLE |
20593  DUK_HOBJECT_FLAG_BUFOBJ |
20594  DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
20595  protobidx);
20596  DUK_ASSERT(h_bufobj != NULL);
20597 
20598  h_bufobj->buf = h_val;
20599  DUK_HBUFFER_INCREF(thr, h_val);
20600  h_bufobj->offset = uint_offset;
20601  h_bufobj->length = uint_length;
20602  h_bufobj->shift = (tmp >> 4) & 0x0f;
20603  h_bufobj->elem_type = (tmp >> 8) & 0xff;
20604  h_bufobj->is_typedarray = tmp & 0x0f;
20605  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
20606 
20607  /* TypedArray views need an automatic ArrayBuffer which must be
20608  * provided as .buffer property of the view. The ArrayBuffer is
20609  * referenced via duk_hbufobj->buf_prop and an inherited .buffer
20610  * accessor returns it.
20611  *
20612  * The ArrayBuffer offset is always set to zero, so that if one
20613  * accesses the ArrayBuffer at the view's .byteOffset, the value
20614  * matches the view at index 0.
20615  */
20616  if (flags & DUK_BUFOBJ_CREATE_ARRBUF) {
20617  duk_hbufobj *h_arrbuf;
20618 
20619  h_arrbuf = duk_push_bufobj_raw(ctx,
20620  DUK_HOBJECT_FLAG_EXTENSIBLE |
20621  DUK_HOBJECT_FLAG_BUFOBJ |
20622  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
20623  DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
20624  DUK_ASSERT(h_arrbuf != NULL);
20625 
20626  h_arrbuf->buf = h_val;
20627  DUK_HBUFFER_INCREF(thr, h_val);
20628  h_arrbuf->offset = 0;
20629  h_arrbuf->length = uint_offset + uint_length; /* Wrap checked above. */
20630  DUK_ASSERT(h_arrbuf->shift == 0);
20631  h_arrbuf->elem_type = DUK_HBUFOBJ_ELEM_UINT8;
20632  DUK_ASSERT(h_arrbuf->is_typedarray == 0);
20633  DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
20634  DUK_ASSERT(h_arrbuf->buf_prop == NULL);
20635 
20636  DUK_ASSERT(h_bufobj->buf_prop == NULL);
20637  h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
20638  DUK_HBUFOBJ_INCREF(thr, h_arrbuf); /* Now reachable and accounted for. */
20639 
20640  duk_pop(ctx);
20641  }
20642 
20643  return;
20644 
20645  range_error:
20646  DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
20647  return; /* not reached */
20648 
20649  arg_error:
20650  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
20651  return; /* not reached */
20652 }
20653 #else /* DUK_USE_BUFFEROBJECT_SUPPORT */
20654 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) {
20655  DUK_UNREF(idx_buffer);
20656  DUK_UNREF(byte_offset);
20657  DUK_UNREF(byte_length);
20658  DUK_UNREF(flags);
20659  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
20660 }
20661 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
20662 
20663 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) {
20664  duk_hthread *thr = (duk_hthread *) ctx;
20665  duk_hobject *proto;
20666 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
20667  duk_bool_t noblame_fileline;
20668 #endif
20669 
20670  DUK_ASSERT_CTX_VALID(ctx);
20671  DUK_ASSERT(thr != NULL);
20672  DUK_UNREF(filename);
20673  DUK_UNREF(line);
20674 
20675  /* Error code also packs a tracedata related flag. */
20676 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
20677  noblame_fileline = err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE;
20678 #endif
20679  err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
20680 
20681  /* error gets its 'name' from the prototype */
20682  proto = duk_error_prototype_from_code(thr, err_code);
20683  (void) duk_push_object_helper_proto(ctx,
20684  DUK_HOBJECT_FLAG_EXTENSIBLE |
20685  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
20686  proto);
20687 
20688  /* ... and its 'message' from an instance property */
20689  if (fmt) {
20690  duk_push_vsprintf(ctx, fmt, ap);
20691  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
20692  } else {
20693  /* If no explicit message given, put error code into message field
20694  * (as a number). This is not fully in keeping with the Ecmascript
20695  * error model because messages are supposed to be strings (Error
20696  * constructors use ToString() on their argument). However, it's
20697  * probably more useful than having a separate 'code' property.
20698  */
20699  duk_push_int(ctx, err_code);
20700  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
20701  }
20702 
20703  /* XXX: .code = err_code disabled, not sure if useful */
20704 
20705  /* Creation time error augmentation */
20706 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
20707  /* filename may be NULL in which case file/line is not recorded */
20708  duk_err_augment_error_create(thr, thr, filename, line, noblame_fileline); /* may throw an error */
20709 #endif
20710 
20711  return duk_get_top_index_unsafe(ctx);
20712 }
20713 
20714 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, ...) {
20715  va_list ap;
20716  duk_idx_t ret;
20717 
20718  DUK_ASSERT_CTX_VALID(ctx);
20719 
20720  va_start(ap, fmt);
20721  ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
20722  va_end(ap);
20723  return ret;
20724 }
20725 
20726 #if !defined(DUK_USE_VARIADIC_MACROS)
20727 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
20728  const char *filename = duk_api_global_filename;
20729  duk_int_t line = duk_api_global_line;
20730  va_list ap;
20731  duk_idx_t ret;
20732 
20733  DUK_ASSERT_CTX_VALID(ctx);
20734 
20735  duk_api_global_filename = NULL;
20736  duk_api_global_line = 0;
20737  va_start(ap, fmt);
20738  ret = duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
20739  va_end(ap);
20740  return ret;
20741 }
20742 #endif /* DUK_USE_VARIADIC_MACROS */
20743 
20744 DUK_EXTERNAL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags) {
20745  duk_hthread *thr = (duk_hthread *) ctx;
20746  duk_tval *tv_slot;
20747  duk_hbuffer *h;
20748  void *buf_data;
20749 
20750  DUK_ASSERT_CTX_VALID(ctx);
20751 
20752  /* check stack first */
20753  if (thr->valstack_top >= thr->valstack_end) {
20754  DUK_ERROR_RANGE_PUSH_BEYOND(thr);
20755  }
20756 
20757  /* Check for maximum buffer length. */
20758  if (size > DUK_HBUFFER_MAX_BYTELEN) {
20759  DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
20760  }
20761 
20762  h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
20763  if (!h) {
20764  DUK_ERROR_ALLOC_FAILED(thr);
20765  }
20766 
20767  tv_slot = thr->valstack_top;
20768  DUK_TVAL_SET_BUFFER(tv_slot, h);
20769  DUK_HBUFFER_INCREF(thr, h);
20770  thr->valstack_top++;
20771 
20772  return (void *) buf_data;
20773 }
20774 
20775 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_context *ctx, duk_size_t len) {
20776  return duk_push_buffer_raw(ctx, len, DUK_BUF_FLAG_NOZERO);
20777 }
20778 
20779 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_context *ctx, duk_size_t len) {
20780  void *ptr;
20781  ptr = duk_push_buffer_raw(ctx, len, 0);
20782 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
20783  /* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
20784  * is not set.
20785  */
20786  DUK_MEMZERO((void *) ptr, (size_t) len);
20787 #endif
20788  return ptr;
20789 }
20790 
20791 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
20792  duk_hthread *thr = (duk_hthread *) ctx;
20793  duk_idx_t ret;
20794 
20795  DUK_ASSERT_CTX_VALID(ctx);
20796 
20797  /* Reviving an object using a heap pointer is a dangerous API
20798  * operation: if the application doesn't guarantee that the
20799  * pointer target is always reachable, difficult-to-diagnose
20800  * problems may ensue. Try to validate the 'ptr' argument to
20801  * the extent possible.
20802  */
20803 
20804 #if defined(DUK_USE_ASSERTIONS)
20805  {
20806  /* One particular problem case is where an object has been
20807  * queued for finalization but the finalizer hasn't been
20808  * executed.
20809  */
20810  duk_heaphdr *curr;
20811  for (curr = thr->heap->finalize_list;
20812  curr != NULL;
20813  curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
20814  DUK_ASSERT(curr != (duk_heaphdr *) ptr);
20815  }
20816  }
20817 #endif
20818 
20819  ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
20820 
20821  if (ptr == NULL) {
20822  goto push_undefined;
20823  }
20824 
20825  switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
20826  case DUK_HTYPE_STRING:
20827  duk_push_hstring(ctx, (duk_hstring *) ptr);
20828  break;
20829  case DUK_HTYPE_OBJECT:
20830  duk_push_hobject(ctx, (duk_hobject *) ptr);
20831  break;
20832  case DUK_HTYPE_BUFFER:
20833  duk_push_hbuffer(ctx, (duk_hbuffer *) ptr);
20834  break;
20835  default:
20836  goto push_undefined;
20837  }
20838  return ret;
20839 
20840  push_undefined:
20841  duk_push_undefined(ctx);
20842  return ret;
20843 }
20844 
20845 /* Push object with no prototype, i.e. a "bare" object. */
20846 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_context *ctx) {
20847  (void) duk_push_object_helper(ctx,
20848  DUK_HOBJECT_FLAG_EXTENSIBLE |
20849  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
20850  -1); /* no prototype */
20851  return duk_get_top_index_unsafe(ctx);
20852 }
20853 
20854 DUK_INTERNAL void duk_push_hstring(duk_context *ctx, duk_hstring *h) {
20855  duk_tval tv;
20856  DUK_ASSERT_CTX_VALID(ctx);
20857  DUK_ASSERT(h != NULL);
20858  DUK_TVAL_SET_STRING(&tv, h);
20859  duk_push_tval(ctx, &tv);
20860 }
20861 
20862 DUK_INTERNAL void duk_push_hstring_stridx(duk_context *ctx, duk_small_uint_t stridx) {
20863  duk_hthread *thr = (duk_hthread *) ctx;
20864  DUK_UNREF(thr);
20865  DUK_ASSERT_STRIDX_VALID(stridx);
20866  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, stridx));
20867 }
20868 
20869 DUK_INTERNAL void duk_push_hstring_empty(duk_context *ctx) {
20870  duk_hthread *thr = (duk_hthread *) ctx;
20871  DUK_UNREF(thr);
20872  duk_push_hstring(ctx, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
20873 }
20874 
20875 DUK_INTERNAL void duk_push_hobject(duk_context *ctx, duk_hobject *h) {
20876  duk_tval tv;
20877  DUK_ASSERT_CTX_VALID(ctx);
20878  DUK_ASSERT(h != NULL);
20879  DUK_TVAL_SET_OBJECT(&tv, h);
20880  duk_push_tval(ctx, &tv);
20881 }
20882 
20883 DUK_INTERNAL void duk_push_hbuffer(duk_context *ctx, duk_hbuffer *h) {
20884  duk_tval tv;
20885  DUK_ASSERT_CTX_VALID(ctx);
20886  DUK_ASSERT(h != NULL);
20887  DUK_TVAL_SET_BUFFER(&tv, h);
20888  duk_push_tval(ctx, &tv);
20889 }
20890 
20891 DUK_INTERNAL void duk_push_hobject_bidx(duk_context *ctx, duk_small_int_t builtin_idx) {
20892  duk_hthread *thr = (duk_hthread *) ctx;
20893  DUK_ASSERT_CTX_VALID(ctx);
20894  DUK_ASSERT(thr != NULL);
20895  DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
20896  DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
20897  duk_push_hobject(ctx, thr->builtins[builtin_idx]);
20898 }
20899 
20900 /*
20901  * Poppers
20902  */
20903 
20904 DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count) {
20905  duk_hthread *thr = (duk_hthread *) ctx;
20906  duk_tval *tv;
20907 #if defined(DUK_USE_REFERENCE_COUNTING)
20908  duk_tval *tv_end;
20909 #endif
20910 
20911  DUK_ASSERT_CTX_VALID(ctx);
20912 
20913  if (DUK_UNLIKELY(count < 0)) {
20914  DUK_ERROR_RANGE_INVALID_COUNT(thr);
20915  return;
20916  }
20917 
20918  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
20919  if (DUK_UNLIKELY((duk_size_t) (thr->valstack_top - thr->valstack_bottom) < (duk_size_t) count)) {
20920  DUK_ERROR_RANGE_INVALID_COUNT(thr);
20921  }
20922 
20923  /*
20924  * Must be very careful here, every DECREF may cause reallocation
20925  * of our valstack.
20926  */
20927 
20928  /* XXX: inlined DECREF macro would be nice here: no NULL check,
20929  * refzero queueing but no refzero algorithm run (= no pointer
20930  * instability), inline code.
20931  */
20932 
20933  /* XXX: optimize loops */
20934 
20935 #if defined(DUK_USE_REFERENCE_COUNTING)
20936  tv = thr->valstack_top;
20937  tv_end = tv - count;
20938  while (tv != tv_end) {
20939  tv--;
20940  DUK_ASSERT(tv >= thr->valstack_bottom);
20941  DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
20942  }
20943  thr->valstack_top = tv;
20944  DUK_REFZERO_CHECK_FAST(thr);
20945 #else
20946  tv = thr->valstack_top;
20947  while (count > 0) {
20948  count--;
20949  tv--;
20950  DUK_ASSERT(tv >= thr->valstack_bottom);
20951  DUK_TVAL_SET_UNDEFINED(tv);
20952  }
20953  thr->valstack_top = tv;
20954 #endif
20955 
20956  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
20957 }
20958 
20959 /* Popping one element is called so often that when footprint is not an issue,
20960  * compile a specialized function for it.
20961  */
20962 #if defined(DUK_USE_PREFER_SIZE)
20963 DUK_EXTERNAL void duk_pop(duk_context *ctx) {
20964  DUK_ASSERT_CTX_VALID(ctx);
20965  duk_pop_n(ctx, 1);
20966 }
20967 #else
20968 DUK_EXTERNAL void duk_pop(duk_context *ctx) {
20969  duk_hthread *thr = (duk_hthread *) ctx;
20970  duk_tval *tv;
20971  DUK_ASSERT_CTX_VALID(ctx);
20972 
20973  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
20974  if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
20975  DUK_ERROR_RANGE_INVALID_COUNT(thr);
20976  }
20977 
20978  tv = --thr->valstack_top; /* tv points to element just below prev top */
20979  DUK_ASSERT(tv >= thr->valstack_bottom);
20980 #if defined(DUK_USE_REFERENCE_COUNTING)
20981  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
20982 #else
20983  DUK_TVAL_SET_UNDEFINED(tv);
20984 #endif
20985  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
20986 }
20987 #endif /* !DUK_USE_PREFER_SIZE */
20988 
20989 /* Unsafe internal variant which assumes there are enough values on the value
20990  * stack so that a top check can be skipped safely.
20991  */
20992 #if defined(DUK_USE_PREFER_SIZE)
20993 DUK_INTERNAL void duk_pop_unsafe(duk_context *ctx) {
20994  DUK_ASSERT_CTX_VALID(ctx);
20995  duk_pop_n(ctx, 1);
20996 }
20997 #else
20998 DUK_INTERNAL void duk_pop_unsafe(duk_context *ctx) {
20999  duk_hthread *thr = (duk_hthread *) ctx;
21000  duk_tval *tv;
21001  DUK_ASSERT_CTX_VALID(ctx);
21002 
21003  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
21004  DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
21005 
21006  tv = --thr->valstack_top; /* tv points to element just below prev top */
21007  DUK_ASSERT(tv >= thr->valstack_bottom);
21008 #if defined(DUK_USE_REFERENCE_COUNTING)
21009  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv); /* side effects */
21010 #else
21011  DUK_TVAL_SET_UNDEFINED(tv);
21012 #endif
21013  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
21014 }
21015 #endif /* !DUK_USE_PREFER_SIZE */
21016 
21017 DUK_EXTERNAL void duk_pop_2(duk_context *ctx) {
21018  DUK_ASSERT_CTX_VALID(ctx);
21019  duk_pop_n(ctx, 2);
21020 }
21021 
21022 DUK_EXTERNAL void duk_pop_3(duk_context *ctx) {
21023  DUK_ASSERT_CTX_VALID(ctx);
21024  duk_pop_n(ctx, 3);
21025 }
21026 
21027 /*
21028  * Pack and unpack (pack value stack entries into an array and vice versa)
21029  */
21030 
21031 /* XXX: pack index range? array index offset? */
21032 DUK_INTERNAL void duk_pack(duk_context *ctx, duk_idx_t count) {
21033  duk_hthread *thr;
21034  duk_harray *a;
21035  duk_tval *tv_src;
21036  duk_tval *tv_dst;
21037  duk_tval *tv_curr;
21038  duk_tval *tv_limit;
21039  duk_idx_t top;
21040 
21041  DUK_ASSERT_CTX_VALID(ctx);
21042  thr = (duk_hthread *) ctx;
21043 
21044  top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
21045  if (count < 0 || count > top) {
21046  DUK_ERROR_RANGE_INVALID_COUNT(thr);
21047  return;
21048  }
21049 
21050  /* Wrapping is controlled by the check above: value stack top can be
21051  * at most thr->valstack_max which is low enough so that multiplying
21052  * with sizeof(duk_tval) won't wrap.
21053  */
21054  DUK_ASSERT(count >= 0 && count <= (duk_idx_t) thr->valstack_max);
21055  DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval)); /* no wrapping */
21056 
21057  a = duk_push_harray_with_size(ctx, (duk_uint32_t) count); /* XXX: uninitialized would be OK */
21058  DUK_ASSERT(a != NULL);
21059  DUK_ASSERT(DUK_HOBJECT_GET_ASIZE((duk_hobject *) a) == (duk_uint32_t) count);
21060  DUK_ASSERT(count == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a) != NULL);
21061  DUK_ASSERT((duk_idx_t) a->length == count);
21062 
21063  /* Copy value stack values directly to the array part without
21064  * any refcount updates: net refcount changes are zero.
21065  */
21066 
21067  tv_src = thr->valstack_top - count - 1;
21068  tv_dst = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
21069  DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
21070 
21071  /* Overwrite result array to final value stack location and wipe
21072  * the rest; no refcount operations needed.
21073  */
21074 
21075  tv_dst = tv_src; /* when count == 0, same as tv_src (OK) */
21076  tv_src = thr->valstack_top - 1;
21077  DUK_TVAL_SET_TVAL(tv_dst, tv_src);
21078 
21079  /* XXX: internal helper to wipe a value stack segment? */
21080  tv_curr = tv_dst + 1;
21081  tv_limit = thr->valstack_top;
21082  while (tv_curr != tv_limit) {
21083  /* Wipe policy: keep as 'undefined'. */
21084  DUK_TVAL_SET_UNDEFINED(tv_curr);
21085  tv_curr++;
21086  }
21087  thr->valstack_top = tv_dst + 1;
21088 }
21089 
21090 #if 0
21091 /* XXX: unpack to position? */
21092 DUK_INTERNAL void duk_unpack(duk_context *ctx) {
21093  /* - dense with length <= a_part
21094  * - dense with length > a_part
21095  * - sparse
21096  * - array-like but not actually an array?
21097  * - how to deal with 'unused' values (gaps); inherit or ignore?
21098  */
21099 }
21100 #endif
21101 
21102 /*
21103  * Error throwing
21104  */
21105 
21106 DUK_EXTERNAL void duk_throw_raw(duk_context *ctx) {
21107  duk_hthread *thr = (duk_hthread *) ctx;
21108 
21109  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
21110  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
21111  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
21112 
21113  if (thr->valstack_top == thr->valstack_bottom) {
21114  DUK_ERROR_TYPE_INVALID_ARGS(thr);
21115  }
21116 
21117  /* Errors are augmented when they are created, not when they are
21118  * thrown or re-thrown. The current error handler, however, runs
21119  * just before an error is thrown.
21120  */
21121 
21122  /* Sync so that augmentation sees up-to-date activations, NULL
21123  * thr->ptr_curr_pc so that it's not used if side effects occur
21124  * in augmentation or longjmp handling.
21125  */
21126  duk_hthread_sync_and_null_currpc(thr);
21127 
21128 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
21129  DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
21130  duk_err_augment_error_throw(thr);
21131 #endif
21132  DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(ctx, -1)));
21133 
21134  duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
21135 
21136  /* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
21137  * need to check that here. If the value is NULL, a fatal error occurs
21138  * because we can't return.
21139  */
21140 
21141  duk_err_longjmp(thr);
21142  DUK_UNREACHABLE();
21143 }
21144 
21145 DUK_EXTERNAL void duk_fatal_raw(duk_context *ctx, const char *err_msg) {
21146  duk_hthread *thr = (duk_hthread *) ctx;
21147 
21148  DUK_ASSERT_CTX_VALID(ctx);
21149  DUK_ASSERT(thr != NULL);
21150  DUK_ASSERT(thr->heap != NULL);
21151  DUK_ASSERT(thr->heap->fatal_func != NULL);
21152 
21153  DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
21154 
21155  /* fatal_func should be noreturn, but noreturn declarations on function
21156  * pointers has a very spotty support apparently so it's not currently
21157  * done.
21158  */
21159  thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
21160 
21161  /* If the fatal handler returns, all bets are off. It'd be nice to
21162  * print something here but since we don't want to depend on stdio,
21163  * there's no way to do so portably.
21164  */
21165  DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
21166  for (;;) {
21167  /* loop forever, don't return (function marked noreturn) */
21168  }
21169 }
21170 
21171 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) {
21172  DUK_ASSERT_CTX_VALID(ctx);
21173 
21174  duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
21175  (void) duk_throw(ctx);
21176 }
21177 
21178 DUK_EXTERNAL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
21179  va_list ap;
21180 
21181  DUK_ASSERT_CTX_VALID(ctx);
21182 
21183  va_start(ap, fmt);
21184  duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
21185  va_end(ap);
21186  (void) duk_throw(ctx);
21187 }
21188 
21189 #if !defined(DUK_USE_VARIADIC_MACROS)
21190 DUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, va_list ap));
21191 
21192 DUK_LOCAL void duk__throw_error_from_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, va_list ap) {
21193  const char *filename;
21194  duk_int_t line;
21195 
21196  DUK_ASSERT_CTX_VALID(ctx);
21197 
21198  filename = duk_api_global_filename;
21199  line = duk_api_global_line;
21200  duk_api_global_filename = NULL;
21201  duk_api_global_line = 0;
21202 
21203  duk_push_error_object_va_raw(ctx, err_code, filename, line, fmt, ap);
21204  (void) duk_throw(ctx);
21205 }
21206 
21207 #define DUK__ERROR_STASH_SHARED(code) do { \
21208  va_list ap; \
21209  va_start(ap, fmt); \
21210  duk__throw_error_from_stash(ctx, (code), fmt, ap); \
21211  va_end(ap); \
21212  /* Never reached; if return 0 here, gcc/clang will complain. */ \
21213  } while (0)
21214 
21215 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...) {
21216  DUK__ERROR_STASH_SHARED(err_code);
21217 }
21218 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_context *ctx, const char *fmt, ...) {
21219  DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
21220 }
21221 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_context *ctx, const char *fmt, ...) {
21222  DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
21223 }
21224 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_context *ctx, const char *fmt, ...) {
21225  DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
21226 }
21227 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_context *ctx, const char *fmt, ...) {
21228  DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
21229 }
21230 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_context *ctx, const char *fmt, ...) {
21231  DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
21232 }
21233 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_context *ctx, const char *fmt, ...) {
21234  DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
21235 }
21236 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_context *ctx, const char *fmt, ...) {
21237  DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
21238 }
21239 #endif /* DUK_USE_VARIADIC_MACROS */
21240 
21241 /*
21242  * Comparison
21243  */
21244 
21245 DUK_EXTERNAL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2) {
21246  duk_hthread *thr = (duk_hthread *) ctx;
21247  duk_tval *tv1, *tv2;
21248 
21249  DUK_ASSERT_CTX_VALID(ctx);
21250 
21251  tv1 = duk_get_tval(ctx, idx1);
21252  tv2 = duk_get_tval(ctx, idx2);
21253  if ((tv1 == NULL) || (tv2 == NULL)) {
21254  return 0;
21255  }
21256 
21257  /* Coercion may be needed, the helper handles that by pushing the
21258  * tagged values to the stack.
21259  */
21260  return duk_js_equals(thr, tv1, tv2);
21261 }
21262 
21263 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2) {
21264  duk_tval *tv1, *tv2;
21265 
21266  DUK_ASSERT_CTX_VALID(ctx);
21267 
21268  tv1 = duk_get_tval(ctx, idx1);
21269  tv2 = duk_get_tval(ctx, idx2);
21270  if ((tv1 == NULL) || (tv2 == NULL)) {
21271  return 0;
21272  }
21273 
21274  /* No coercions or other side effects, so safe */
21275  return duk_js_strict_equals(tv1, tv2);
21276 }
21277 
21278 DUK_EXTERNAL_DECL duk_bool_t duk_samevalue(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2) {
21279  duk_tval *tv1, *tv2;
21280 
21281  DUK_ASSERT_CTX_VALID(ctx);
21282 
21283  tv1 = duk_get_tval(ctx, idx1);
21284  tv2 = duk_get_tval(ctx, idx2);
21285  if ((tv1 == NULL) || (tv2 == NULL)) {
21286  return 0;
21287  }
21288 
21289  /* No coercions or other side effects, so safe */
21290  return duk_js_samevalue(tv1, tv2);
21291 }
21292 
21293 /*
21294  * instanceof
21295  */
21296 
21297 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2) {
21298  duk_tval *tv1, *tv2;
21299 
21300  DUK_ASSERT_CTX_VALID(ctx);
21301 
21302  /* Index validation is strict, which differs from duk_equals().
21303  * The strict behavior mimics how instanceof itself works, e.g.
21304  * it is a TypeError if rval is not a -callable- object. It would
21305  * be somewhat inconsistent if rval would be allowed to be
21306  * non-existent without a TypeError.
21307  */
21308  tv1 = duk_require_tval(ctx, idx1);
21309  DUK_ASSERT(tv1 != NULL);
21310  tv2 = duk_require_tval(ctx, idx2);
21311  DUK_ASSERT(tv2 != NULL);
21312 
21313  return duk_js_instanceof((duk_hthread *) ctx, tv1, tv2);
21314 }
21315 
21316 /*
21317  * Lightfunc
21318  */
21319 
21320 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_context *ctx, duk_c_function func, duk_small_uint_t lf_flags) {
21321  /* Lightfunc name, includes Duktape/C native function pointer, which
21322  * can often be used to locate the function from a symbol table.
21323  * The name also includes the 16-bit duk_tval flags field because it
21324  * includes the magic value. Because a single native function often
21325  * provides different functionality depending on the magic value, it
21326  * seems reasonably to include it in the name.
21327  *
21328  * On the other hand, a complicated name increases string table
21329  * pressure in low memory environments (but only when function name
21330  * is accessed).
21331  */
21332 
21333  duk_push_sprintf(ctx, "light_");
21334  duk_push_string_funcptr(ctx, (duk_uint8_t *) &func, sizeof(func));
21335  duk_push_sprintf(ctx, "_%04x", (unsigned int) lf_flags);
21336  duk_concat(ctx, 3);
21337 }
21338 
21339 DUK_INTERNAL void duk_push_lightfunc_name(duk_context *ctx, duk_tval *tv) {
21340  duk_c_function func;
21341  duk_small_uint_t lf_flags;
21342 
21343  DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
21344  DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21345  duk_push_lightfunc_name_raw(ctx, func, lf_flags);
21346 }
21347 
21348 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv) {
21349  duk_c_function func;
21350  duk_small_uint_t lf_flags;
21351 
21352  DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
21353  DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags); /* read before 'tv' potentially invalidated */
21354 
21355  duk_push_string(ctx, "function ");
21356  duk_push_lightfunc_name_raw(ctx, func, lf_flags);
21357  duk_push_string(ctx, "() { [lightfunc code] }");
21358  duk_concat(ctx, 3);
21359 }
21360 
21361 /*
21362  * Function pointers
21363  *
21364  * Printing function pointers is non-portable, so we do that by hex printing
21365  * bytes from memory.
21366  */
21367 
21368 DUK_INTERNAL void duk_push_string_funcptr(duk_context *ctx, duk_uint8_t *ptr, duk_size_t sz) {
21369  duk_uint8_t buf[32 * 2];
21370  duk_uint8_t *p, *q;
21371  duk_small_uint_t i;
21372  duk_small_uint_t t;
21373 
21374  DUK_ASSERT(sz <= 32); /* sanity limit for function pointer size */
21375 
21376  p = buf;
21377 #if defined(DUK_USE_INTEGER_LE)
21378  q = ptr + sz;
21379 #else
21380  q = ptr;
21381 #endif
21382  for (i = 0; i < sz; i++) {
21383 #if defined(DUK_USE_INTEGER_LE)
21384  t = *(--q);
21385 #else
21386  t = *(q++);
21387 #endif
21388  *p++ = duk_lc_digits[t >> 4];
21389  *p++ = duk_lc_digits[t & 0x0f];
21390  }
21391 
21392  duk_push_lstring(ctx, (const char *) buf, sz * 2);
21393 }
21394 
21395 /*
21396  * Push readable string summarizing duk_tval. The operation is side effect
21397  * free and will only throw from internal errors (e.g. out of memory).
21398  * This is used by e.g. property access code to summarize a key/base safely,
21399  * and is not intended to be fast (but small and safe).
21400  */
21401 
21402 #define DUK__READABLE_STRING_MAXCHARS 32
21403 
21404 /* String sanitizer which escapes ASCII control characters and a few other
21405  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
21406  * question marks. No errors are thrown for any input string, except in out
21407  * of memory situations.
21408  */
21409 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_context *ctx, duk_hstring *h_input) {
21410  duk_hthread *thr;
21411  const duk_uint8_t *p, *p_start, *p_end;
21412  duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_STRING_MAXCHARS +
21413  2 /*quotes*/ + 3 /*periods*/];
21414  duk_uint8_t *q;
21415  duk_ucodepoint_t cp;
21416  duk_small_uint_t nchars;
21417 
21418  DUK_ASSERT_CTX_VALID(ctx);
21419  DUK_ASSERT(h_input != NULL);
21420  thr = (duk_hthread *) ctx;
21421 
21422  p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
21423  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
21424  p = p_start;
21425  q = buf;
21426 
21427  nchars = 0;
21428  *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
21429  for (;;) {
21430  if (p >= p_end) {
21431  break;
21432  }
21433  if (nchars == DUK__READABLE_STRING_MAXCHARS) {
21434  *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
21435  *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
21436  *q++ = (duk_uint8_t) DUK_ASC_PERIOD;
21437  break;
21438  }
21439  if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
21440  if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
21441  DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4); /* estimate is valid */
21442  DUK_ASSERT((cp >> 4) <= 0x0f);
21443  *q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
21444  *q++ = (duk_uint8_t) DUK_ASC_LC_X;
21445  *q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
21446  *q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
21447  } else {
21448  q += duk_unicode_encode_xutf8(cp, q);
21449  }
21450  } else {
21451  p++; /* advance manually */
21452  *q++ = (duk_uint8_t) DUK_ASC_QUESTION;
21453  }
21454  nchars++;
21455  }
21456  *q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
21457 
21458  duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (q - buf));
21459 }
21460 
21461 DUK_LOCAL const char *duk__push_string_tval_readable(duk_context *ctx, duk_tval *tv, duk_bool_t error_aware) {
21462  duk_hthread *thr;
21463 
21464  DUK_ASSERT_CTX_VALID(ctx);
21465  thr = (duk_hthread *) ctx;
21466  DUK_UNREF(thr);
21467  /* 'tv' may be NULL */
21468 
21469  if (tv == NULL) {
21470  duk_push_string(ctx, "none");
21471  } else {
21472  switch (DUK_TVAL_GET_TAG(tv)) {
21473  case DUK_TAG_STRING: {
21474  /* XXX: symbol support (maybe in summary rework branch) */
21475  duk__push_hstring_readable_unicode(ctx, DUK_TVAL_GET_STRING(tv));
21476  break;
21477  }
21478  case DUK_TAG_OBJECT: {
21479  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
21480  DUK_ASSERT(h != NULL);
21481 
21482  if (error_aware &&
21483  duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
21484  /* Get error message in a side effect free way if
21485  * possible; if not, summarize as a generic object.
21486  * Error message currently gets quoted.
21487  */
21488  /* XXX: better internal getprop call; get without side effects
21489  * but traverse inheritance chain.
21490  */
21491  duk_tval *tv_msg;
21492  tv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));
21493  if (tv_msg) {
21494  /* It's important this summarization is
21495  * not error aware to avoid unlimited
21496  * recursion when the .message property
21497  * is e.g. another error.
21498  */
21499  return duk_push_string_tval_readable(ctx, tv_msg);
21500  }
21501  }
21502  duk_push_class_string_tval(ctx, tv);
21503  break;
21504  }
21505  case DUK_TAG_BUFFER: {
21506  /* While plain buffers mimic Uint8Arrays, they summarize differently.
21507  * This is useful so that the summarized string accurately reflects the
21508  * internal type which may matter for figuring out bugs etc.
21509  */
21510  /* XXX: Hex encoded, length limited buffer summary here? */
21511  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21512  DUK_ASSERT(h != NULL);
21513  duk_push_sprintf(ctx, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
21514  break;
21515  }
21516  case DUK_TAG_POINTER: {
21517  /* Surround with parentheses like in JX, ensures NULL pointer
21518  * is distinguishable from null value ("(null)" vs "null").
21519  */
21520  duk_push_tval(ctx, tv);
21521  duk_push_sprintf(ctx, "(%s)", duk_to_string(ctx, -1));
21522  duk_remove_m2(ctx);
21523  break;
21524  }
21525  default: {
21526  duk_push_tval(ctx, tv);
21527  break;
21528  }
21529  }
21530  }
21531 
21532  return duk_to_string(ctx, -1);
21533 }
21534 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_context *ctx, duk_tval *tv) {
21535  DUK_ASSERT_CTX_VALID(ctx);
21536  return duk__push_string_tval_readable(ctx, tv, 0 /*error_aware*/);
21537 }
21538 
21539 DUK_INTERNAL const char *duk_push_string_readable(duk_context *ctx, duk_idx_t idx) {
21540  DUK_ASSERT_CTX_VALID(ctx);
21541  return duk_push_string_tval_readable(ctx, duk_get_tval(ctx, idx));
21542 }
21543 
21544 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_context *ctx, duk_tval *tv) {
21545  DUK_ASSERT_CTX_VALID(ctx);
21546  return duk__push_string_tval_readable(ctx, tv, 1 /*error_aware*/);
21547 }
21548 
21549 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_context *ctx, duk_hstring *h) {
21550  const duk_uint8_t *p;
21551  const duk_uint8_t *p_end;
21552  const duk_uint8_t *q;
21553 
21554  /* .toString() */
21555  duk_push_string(ctx, "Symbol(");
21556  p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
21557  p_end = p + DUK_HSTRING_GET_BYTELEN(h);
21558  DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
21559  p++;
21560  for (q = p; q < p_end; q++) {
21561  if (*q == 0xffU) {
21562  /* Terminate either at end-of-string (but NUL MUST
21563  * be accepted without terminating description) or
21564  * 0xFF, which is used to mark start of unique trailer
21565  * (and cannot occur in CESU-8 / extended UTF-8).
21566  */
21567  break;
21568  }
21569  }
21570  duk_push_lstring(ctx, (const char *) p, (duk_size_t) (q - p));
21571  duk_push_string(ctx, ")");
21572  duk_concat(ctx, 3);
21573 }
21574 
21575 /* automatic undefs */
21576 #undef DUK__CHECK_SPACE
21577 #undef DUK__ERROR_STASH_SHARED
21578 #undef DUK__PACK_ARGS
21579 #undef DUK__READABLE_STRING_MAXCHARS
21580 /*
21581  * String manipulation
21582  */
21583 
21584 /* #include duk_internal.h -> already included */
21585 
21586 DUK_LOCAL void duk__concat_and_join_helper(duk_context *ctx, duk_idx_t count_in, duk_bool_t is_join) {
21587  duk_hthread *thr = (duk_hthread *) ctx;
21588  duk_uint_t count;
21589  duk_uint_t i;
21590  duk_size_t idx;
21591  duk_size_t len;
21592  duk_hstring *h;
21593  duk_uint8_t *buf;
21594 
21595  DUK_ASSERT_CTX_VALID(ctx);
21596 
21597  if (DUK_UNLIKELY(count_in <= 0)) {
21598  if (count_in < 0) {
21599  DUK_ERROR_RANGE_INVALID_COUNT(thr);
21600  return;
21601  }
21602  DUK_ASSERT(count_in == 0);
21603  duk_push_hstring_empty(ctx);
21604  return;
21605  }
21606  count = (duk_uint_t) count_in;
21607 
21608  if (is_join) {
21609  duk_size_t t1, t2, limit;
21610  h = duk_to_hstring(ctx, -((duk_idx_t) count) - 1);
21611  DUK_ASSERT(h != NULL);
21612 
21613  /* A bit tricky overflow test, see doc/code-issues.rst. */
21614  t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
21615  t2 = (duk_size_t) (count - 1);
21616  limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
21617  if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
21618  /* Combined size of separators already overflows. */
21619  goto error_overflow;
21620  }
21621  len = (duk_size_t) (t1 * t2);
21622  } else {
21623  len = (duk_size_t) 0;
21624  }
21625 
21626  for (i = count; i >= 1; i--) {
21627  duk_size_t new_len;
21628  h = duk_to_hstring(ctx, -((duk_idx_t) i));
21629  new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
21630 
21631  /* Impose a string maximum length, need to handle overflow
21632  * correctly.
21633  */
21634  if (new_len < len || /* wrapped */
21635  new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
21636  goto error_overflow;
21637  }
21638  len = new_len;
21639  }
21640 
21641  DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
21642  (unsigned long) count, (unsigned long) len));
21643 
21644  /* Use stack allocated buffer to ensure reachability in errors
21645  * (e.g. intern error).
21646  */
21647  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, len);
21648  DUK_ASSERT(buf != NULL);
21649 
21650  /* [ ... (sep) str1 str2 ... strN buf ] */
21651 
21652  idx = 0;
21653  for (i = count; i >= 1; i--) {
21654  if (is_join && i != count) {
21655  h = duk_require_hstring(ctx, -((duk_idx_t) count) - 2); /* extra -1 for buffer */
21656  DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
21657  idx += DUK_HSTRING_GET_BYTELEN(h);
21658  }
21659  h = duk_require_hstring(ctx, -((duk_idx_t) i) - 1); /* extra -1 for buffer */
21660  DUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
21661  idx += DUK_HSTRING_GET_BYTELEN(h);
21662  }
21663 
21664  DUK_ASSERT(idx == len);
21665 
21666  /* [ ... (sep) str1 str2 ... strN buf ] */
21667 
21668  /* Get rid of the strings early to minimize memory use before intern. */
21669 
21670  if (is_join) {
21671  duk_replace(ctx, -((duk_idx_t) count) - 2); /* overwrite sep */
21672  duk_pop_n(ctx, count);
21673  } else {
21674  duk_replace(ctx, -((duk_idx_t) count) - 1); /* overwrite str1 */
21675  duk_pop_n(ctx, count-1);
21676  }
21677 
21678  /* [ ... buf ] */
21679 
21680  (void) duk_buffer_to_string(ctx, -1); /* Safe if inputs are safe. */
21681 
21682  /* [ ... res ] */
21683  return;
21684 
21685  error_overflow:
21686  DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
21687 }
21688 
21689 DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
21690  DUK_ASSERT_CTX_VALID(ctx);
21691 
21692  duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
21693 }
21694 
21695 DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
21696  DUK_ASSERT_CTX_VALID(ctx);
21697 
21698  duk__concat_and_join_helper(ctx, count, 1 /*is_join*/);
21699 }
21700 
21701 /* XXX: could map/decode be unified with duk_unicode_support.c code?
21702  * Case conversion needs also the character surroundings though.
21703  */
21704 
21705 DUK_EXTERNAL void duk_decode_string(duk_context *ctx, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
21706  duk_hthread *thr = (duk_hthread *) ctx;
21707  duk_hstring *h_input;
21708  const duk_uint8_t *p, *p_start, *p_end;
21709  duk_codepoint_t cp;
21710 
21711  DUK_ASSERT_CTX_VALID(ctx);
21712 
21713  h_input = duk_require_hstring(ctx, idx); /* Accept symbols. */
21714  DUK_ASSERT(h_input != NULL);
21715 
21716  p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
21717  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
21718  p = p_start;
21719 
21720  for (;;) {
21721  if (p >= p_end) {
21722  break;
21723  }
21724  cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
21725  callback(udata, cp);
21726  }
21727 }
21728 
21729 DUK_EXTERNAL void duk_map_string(duk_context *ctx, duk_idx_t idx, duk_map_char_function callback, void *udata) {
21730  duk_hthread *thr = (duk_hthread *) ctx;
21731  duk_hstring *h_input;
21732  duk_bufwriter_ctx bw_alloc;
21733  duk_bufwriter_ctx *bw;
21734  const duk_uint8_t *p, *p_start, *p_end;
21735  duk_codepoint_t cp;
21736 
21737  DUK_ASSERT_CTX_VALID(ctx);
21738 
21739  idx = duk_normalize_index(ctx, idx);
21740 
21741  h_input = duk_require_hstring(ctx, idx); /* Accept symbols. */
21742  DUK_ASSERT(h_input != NULL);
21743 
21744  bw = &bw_alloc;
21745  DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* Reasonable output estimate. */
21746 
21747  p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
21748  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
21749  p = p_start;
21750 
21751  for (;;) {
21752  /* XXX: could write output in chunks with fewer ensure calls,
21753  * but relative benefit would be small here.
21754  */
21755 
21756  if (p >= p_end) {
21757  break;
21758  }
21759  cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
21760  cp = callback(udata, cp);
21761 
21762  DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
21763  }
21764 
21765  DUK_BW_COMPACT(thr, bw);
21766  (void) duk_buffer_to_string(ctx, -1); /* Safe, extended UTF-8 encoded. */
21767  duk_replace(ctx, idx);
21768 }
21769 
21770 DUK_EXTERNAL void duk_substring(duk_context *ctx, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
21771  duk_hthread *thr = (duk_hthread *) ctx;
21772  duk_hstring *h;
21773  duk_hstring *res;
21774  duk_size_t start_byte_offset;
21775  duk_size_t end_byte_offset;
21776 
21777  DUK_ASSERT_CTX_VALID(ctx);
21778 
21779  idx = duk_require_normalize_index(ctx, idx); /* Accept symbols. */
21780  h = duk_require_hstring(ctx, idx);
21781  DUK_ASSERT(h != NULL);
21782 
21783  if (end_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
21784  end_offset = DUK_HSTRING_GET_CHARLEN(h);
21785  }
21786  if (start_offset > end_offset) {
21787  start_offset = end_offset;
21788  }
21789 
21790  DUK_ASSERT_DISABLE(start_offset >= 0);
21791  DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
21792  DUK_ASSERT_DISABLE(end_offset >= 0);
21793  DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
21794 
21795  /* Guaranteed by string limits. */
21796  DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
21797  DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
21798 
21799  start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
21800  end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
21801 
21802  DUK_ASSERT(end_byte_offset >= start_byte_offset);
21803  DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX); /* Guaranteed by string limits. */
21804 
21805  /* No size check is necessary. */
21806  res = duk_heap_string_intern_checked(thr,
21807  DUK_HSTRING_GET_DATA(h) + start_byte_offset,
21808  (duk_uint32_t) (end_byte_offset - start_byte_offset));
21809 
21810  duk_push_hstring(ctx, res);
21811  duk_replace(ctx, idx);
21812 }
21813 
21814 /* XXX: this is quite clunky. Add Unicode helpers to scan backwards and
21815  * forwards with a callback to process codepoints?
21816  */
21817 DUK_EXTERNAL void duk_trim(duk_context *ctx, duk_idx_t idx) {
21818  duk_hthread *thr = (duk_hthread *) ctx;
21819  duk_hstring *h;
21820  const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2; /* pointers for scanning */
21821  const duk_uint8_t *q_start, *q_end; /* start (incl) and end (excl) of trimmed part */
21822  duk_codepoint_t cp;
21823 
21824  DUK_ASSERT_CTX_VALID(ctx);
21825 
21826  idx = duk_require_normalize_index(ctx, idx); /* Accept symbols. */
21827  h = duk_require_hstring(ctx, idx);
21828  DUK_ASSERT(h != NULL);
21829 
21830  p_start = DUK_HSTRING_GET_DATA(h);
21831  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
21832 
21833  p = p_start;
21834  while (p < p_end) {
21835  p_tmp1 = p;
21836  cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
21837  if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
21838  break;
21839  }
21840  p = p_tmp1;
21841  }
21842  q_start = p;
21843  if (p == p_end) {
21844  /* Entire string is whitespace. */
21845  q_end = p;
21846  goto scan_done;
21847  }
21848 
21849  p = p_end;
21850  while (p > p_start) {
21851  p_tmp1 = p;
21852  while (p > p_start) {
21853  p--;
21854  if (((*p) & 0xc0) != 0x80) {
21855  break;
21856  }
21857  }
21858  p_tmp2 = p;
21859 
21860  cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
21861  if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
21862  p = p_tmp1;
21863  break;
21864  }
21865  }
21866  q_end = p;
21867 
21868  scan_done:
21869  /* This may happen when forward and backward scanning disagree
21870  * (possible for non-extended-UTF-8 strings).
21871  */
21872  if (q_end < q_start) {
21873  q_end = q_start;
21874  }
21875 
21876  DUK_ASSERT(q_start >= p_start && q_start <= p_end);
21877  DUK_ASSERT(q_end >= p_start && q_end <= p_end);
21878  DUK_ASSERT(q_end >= q_start);
21879 
21880  DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
21881  (const void *) p_start, (const void *) p_end,
21882  (const void *) q_start, (const void *) q_end));
21883 
21884  if (q_start == p_start && q_end == p_end) {
21885  DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
21886  return;
21887  }
21888 
21889  duk_push_lstring(ctx, (const char *) q_start, (duk_size_t) (q_end - q_start));
21890  duk_replace(ctx, idx);
21891 }
21892 
21893 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t idx, duk_size_t char_offset) {
21894  duk_hthread *thr = (duk_hthread *) ctx;
21895  duk_hstring *h;
21896  duk_ucodepoint_t cp;
21897 
21898  DUK_ASSERT_CTX_VALID(ctx);
21899 
21900  /* XXX: Share code with String.prototype.charCodeAt? Main difference
21901  * is handling of clamped offsets.
21902  */
21903 
21904  h = duk_require_hstring(ctx, idx); /* Accept symbols. */
21905  DUK_ASSERT(h != NULL);
21906 
21907  DUK_ASSERT_DISABLE(char_offset >= 0); /* Always true, arg is unsigned. */
21908  if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
21909  return 0;
21910  }
21911 
21912  DUK_ASSERT(char_offset <= DUK_UINT_MAX); /* Guaranteed by string limits. */
21913  cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
21914  return (duk_codepoint_t) cp;
21915 }
21916 /*
21917  * Date/time.
21918  */
21919 
21920 /* #include duk_internal.h -> already included */
21921 
21922 DUK_EXTERNAL duk_double_t duk_get_now(duk_context *ctx) {
21923  return ((duk_double_t) DUK_USE_DATE_GET_NOW((ctx)));
21924 }
21925 
21926 DUK_EXTERNAL void duk_time_to_components(duk_context *ctx, duk_double_t timeval, duk_time_components *comp) {
21927  duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
21928  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
21929  duk_uint_t flags;
21930 
21931  DUK_ASSERT(ctx != NULL);
21932  DUK_ASSERT(comp != NULL); /* XXX: or check? */
21933  DUK_UNREF(ctx);
21934 
21935  /* Convert as one-based, but change month to zero-based to match the
21936  * Ecmascript Date built-in behavior 1:1.
21937  */
21938  flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
21939 
21940  duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
21941 
21942  DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
21943  comp->year = dparts[DUK_DATE_IDX_YEAR];
21944  comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
21945  comp->day = dparts[DUK_DATE_IDX_DAY];
21946  comp->hours = dparts[DUK_DATE_IDX_HOUR];
21947  comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
21948  comp->seconds = dparts[DUK_DATE_IDX_SECOND];
21949  comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
21950  comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
21951 }
21952 
21953 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_context *ctx, duk_time_components *comp) {
21954  duk_double_t d;
21955  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
21956  duk_uint_t flags;
21957 
21958  DUK_ASSERT(ctx != NULL);
21959  DUK_ASSERT(comp != NULL); /* XXX: or check? */
21960  DUK_UNREF(ctx);
21961 
21962  /* Match Date constructor behavior (with UTC time). Month is given
21963  * as zero-based. Day-of-month is given as one-based so normalize
21964  * it to zero-based as the internal conversion helpers expects all
21965  * components to be zero-based.
21966  */
21967  flags = 0;
21968 
21969  /* XXX: expensive conversion; use array format in API instead, or unify
21970  * time provider and time API to use same struct?
21971  */
21972 
21973  dparts[DUK_DATE_IDX_YEAR] = comp->year;
21974  dparts[DUK_DATE_IDX_MONTH] = comp->month;
21975  dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
21976  dparts[DUK_DATE_IDX_HOUR] = comp->hours;
21977  dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
21978  dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
21979  dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
21980  dparts[DUK_DATE_IDX_WEEKDAY] = 0; /* ignored */
21981 
21982  d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
21983 
21984  return d;
21985 }
21986 /*
21987  * Array built-ins
21988  *
21989  * Most Array built-ins are intentionally generic in Ecmascript, and are
21990  * intended to work even when the 'this' binding is not an Array instance.
21991  * This Ecmascript feature is also used by much real world code. For this
21992  * reason the implementations here don't assume exotic Array behavior or
21993  * e.g. presence of a .length property. However, some algorithms have a
21994  * fast path for duk_harray backed actual Array instances, enabled when
21995  * footprint is not a concern.
21996  *
21997  * XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
21998  * [[Delete]] operations, but it's currently false throughout. Go through
21999  * all put/delete cases and check throw flag use. Need a new API primitive
22000  * which allows throws flag to be specified.
22001  *
22002  * XXX: array lengths above 2G won't work reliably. There are many places
22003  * where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
22004  * i.e. -33- bits). Although array 'length' cannot be written to be outside
22005  * the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
22006  * some intermediate values may be above 0xffffffff and this may not be always
22007  * correctly handled now (duk_uint32_t is not enough for all algorithms).
22008  * For instance, push() can legitimately write entries beyond length 0xffffffff
22009  * and cause a RangeError only at the end. To do this properly, the current
22010  * push() implementation tracks the array index using a 'double' instead of a
22011  * duk_uint32_t (which is somewhat awkward). See test-bi-array-push-maxlen.js.
22012  *
22013  * On using "put" vs. "def" prop
22014  * =============================
22015  *
22016  * Code below must be careful to use the appropriate primitive as it matters
22017  * for compliance. When using "put" there may be inherited properties in
22018  * Array.prototype which cause side effects when values are written. When
22019  * using "define" there are no such side effects, and many test262 test cases
22020  * check for this (for real world code, such side effects are very rare).
22021  * Both "put" and "define" are used in the E5.1 specification; as a rule,
22022  * "put" is used when modifying an existing array (or a non-array 'this'
22023  * binding) and "define" for setting values into a fresh result array.
22024  */
22025 
22026 /* #include duk_internal.h -> already included */
22027 
22028 /* Perform an intermediate join when this many elements have been pushed
22029  * on the value stack.
22030  */
22031 #define DUK__ARRAY_MID_JOIN_LIMIT 4096
22032 
22033 #if defined(DUK_USE_ARRAY_BUILTIN)
22034 
22035 /*
22036  * Shared helpers.
22037  */
22038 
22039 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
22040  * on the value stack and object coerced, and the current .length is returned.
22041  * Note that length is left on stack (it could be popped, but that's not
22042  * usually necessary because call handling will clean it up automatically).
22043  */
22044 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) {
22045  duk_uint32_t len;
22046 
22047  /* XXX: push more directly? */
22048  (void) duk_push_this_coercible_to_object(ctx);
22049  DUK_ASSERT_HOBJECT_VALID(duk_get_hobject(ctx, -1));
22050  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_LENGTH);
22051  len = duk_to_uint32(ctx, -1);
22052 
22053  /* -> [ ... ToObject(this) ToUint32(length) ] */
22054  return len;
22055 }
22056 
22057 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_context *ctx) {
22058  /* Range limited to [0, 0x7fffffff] range, i.e. range that can be
22059  * represented with duk_int32_t. Use this when the method doesn't
22060  * handle the full 32-bit unsigned range correctly.
22061  */
22062  duk_uint32_t ret = duk__push_this_obj_len_u32(ctx);
22063  if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
22064  DUK_ERROR_RANGE_INVALID_LENGTH((duk_hthread *) ctx);
22065  }
22066  return ret;
22067 }
22068 
22069 #if defined(DUK_USE_ARRAY_FASTPATH)
22070 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
22071  * a few other guarantees for fast path operation. The fast path doesn't
22072  * need to handle all operations, even for duk_harrays, but must handle a
22073  * significant fraction to improve performance. Return a non-NULL duk_harray
22074  * pointer when all fast path criteria are met, NULL otherwise.
22075  */
22076 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_context *ctx) {
22077  duk_hthread *thr;
22078  duk_tval *tv;
22079  duk_hobject *h;
22080  duk_uint_t flags_mask, flags_bits, flags_value;
22081 
22082  thr = (duk_hthread *) ctx;
22083  DUK_ASSERT(thr->valstack_bottom > thr->valstack); /* because call in progress */
22084  tv = DUK_GET_THIS_TVAL_PTR(thr);
22085 
22086  /* Fast path requires that 'this' is a duk_harray. Read only arrays
22087  * (ROM backed) are also rejected for simplicity.
22088  */
22089  if (!DUK_TVAL_IS_OBJECT(tv)) {
22090  DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
22091  return NULL;
22092  }
22093  h = DUK_TVAL_GET_OBJECT(tv);
22094  DUK_ASSERT(h != NULL);
22095  flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
22096  DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
22097  DUK_HEAPHDR_FLAG_READONLY;
22098  flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
22099  DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
22100  flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
22101  if ((flags_value & flags_mask) != flags_bits) {
22102  DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
22103  return NULL;
22104  }
22105 
22106  /* In some cases a duk_harray's 'length' may be larger than the
22107  * current array part allocation. Avoid the fast path in these
22108  * cases, so that all fast path code can safely assume that all
22109  * items in the range [0,length[ are backed by the current array
22110  * part allocation.
22111  */
22112  if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
22113  DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
22114  return NULL;
22115  }
22116 
22117  /* Guarantees for fast path. */
22118  DUK_ASSERT(h != NULL);
22119  DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
22120  DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
22121 
22122  DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
22123  return (duk_harray *) h;
22124 }
22125 #endif /* DUK_USE_ARRAY_FASTPATH */
22126 
22127 /*
22128  * Constructor
22129  */
22130 
22131 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_context *ctx) {
22132  duk_idx_t nargs;
22133  duk_harray *a;
22134  duk_double_t d;
22135  duk_uint32_t len;
22136  duk_uint32_t len_prealloc;
22137 
22138  nargs = duk_get_top(ctx);
22139 
22140  if (nargs == 1 && duk_is_number(ctx, 0)) {
22141  /* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
22142  d = duk_get_number(ctx, 0);
22143  len = duk_to_uint32(ctx, 0);
22144  if (((duk_double_t) len) != d) {
22145  DUK_DCERROR_RANGE_INVALID_LENGTH((duk_hthread *) ctx);
22146  }
22147 
22148  /* For small lengths create a dense preallocated array.
22149  * For large arrays preallocate an initial part.
22150  */
22151  len_prealloc = len < 64 ? len : 64;
22152  a = duk_push_harray_with_size(ctx, len_prealloc);
22153  DUK_ASSERT(a != NULL);
22154  a->length = len;
22155  return 1;
22156  }
22157 
22158  duk_pack(ctx, nargs);
22159  return 1;
22160 }
22161 
22162 /*
22163  * isArray()
22164  */
22165 
22166 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx) {
22167  duk_hobject *h;
22168 
22169  h = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_ARRAY);
22170  duk_push_boolean(ctx, (h != NULL));
22171  return 1;
22172 }
22173 
22174 /*
22175  * toString()
22176  */
22177 
22178 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
22179  (void) duk_push_this_coercible_to_object(ctx);
22180  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_JOIN);
22181 
22182  /* [ ... this func ] */
22183  if (!duk_is_callable(ctx, -1)) {
22184  /* Fall back to the initial (original) Object.toString(). We don't
22185  * currently have pointers to the built-in functions, only the top
22186  * level global objects (like "Array") so this is now done in a bit
22187  * of a hacky manner. It would be cleaner to push the (original)
22188  * function and use duk_call_method().
22189  */
22190 
22191  /* XXX: 'this' will be ToObject() coerced twice, which is incorrect
22192  * but should have no visible side effects.
22193  */
22194  DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
22195  duk_set_top(ctx, 0);
22196  return duk_bi_object_prototype_to_string(ctx); /* has access to 'this' binding */
22197  }
22198 
22199  /* [ ... this func ] */
22200 
22201  duk_insert(ctx, -2);
22202 
22203  /* [ ... func this ] */
22204 
22205  DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
22206  (duk_tval *) duk_get_tval(ctx, -2),
22207  (duk_tval *) duk_get_tval(ctx, -1)));
22208  duk_call_method(ctx, 0);
22209 
22210  return 1;
22211 }
22212 
22213 /*
22214  * concat()
22215  */
22216 
22217 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) {
22218  duk_idx_t i, n;
22219  duk_uarridx_t idx, idx_last;
22220  duk_uarridx_t j, len;
22221  duk_hobject *h;
22222 
22223  /* XXX: the insert here is a bit expensive if there are a lot of items.
22224  * It could also be special cased in the outermost for loop quite easily
22225  * (as the element is dup()'d anyway).
22226  */
22227 
22228  (void) duk_push_this_coercible_to_object(ctx);
22229  duk_insert(ctx, 0);
22230  n = duk_get_top(ctx);
22231  duk_push_array(ctx); /* -> [ ToObject(this) item1 ... itemN arr ] */
22232 
22233  /* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
22234  * (which differs from the official algorithm). If no error is thrown, this
22235  * doesn't matter as the length is updated at the end. However, if an error
22236  * is thrown, the length will be unset. That shouldn't matter because the
22237  * caller won't get a reference to the intermediate value.
22238  */
22239 
22240  idx = 0;
22241  idx_last = 0;
22242  for (i = 0; i < n; i++) {
22243  DUK_ASSERT_TOP(ctx, n + 1);
22244 
22245  /* [ ToObject(this) item1 ... itemN arr ] */
22246 
22247  duk_dup(ctx, i);
22248  h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
22249  if (!h) {
22250  duk_xdef_prop_index_wec(ctx, -2, idx++);
22251  idx_last = idx;
22252  continue;
22253  }
22254 
22255  /* [ ToObject(this) item1 ... itemN arr item(i) ] */
22256 
22257  /* XXX: an array can have length higher than 32 bits; this is not handled
22258  * correctly now.
22259  */
22260  len = (duk_uarridx_t) duk_get_length(ctx, -1);
22261  for (j = 0; j < len; j++) {
22262  if (duk_get_prop_index(ctx, -1, j)) {
22263  /* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
22264  duk_xdef_prop_index_wec(ctx, -3, idx++);
22265  idx_last = idx;
22266  } else {
22267  idx++;
22268  duk_pop(ctx);
22269 #if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
22270  /* According to E5.1 Section 15.4.4.4 nonexistent trailing
22271  * elements do not affect 'length' of the result. Test262
22272  * and other engines disagree, so update idx_last here too.
22273  */
22274  idx_last = idx;
22275 #else
22276  /* Strict standard behavior, ignore trailing elements for
22277  * result 'length'.
22278  */
22279 #endif
22280  }
22281  }
22282  duk_pop(ctx);
22283  }
22284 
22285  /* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
22286  * in the end, but because we're operating with an internal value which
22287  * is known to be an array, this should be equivalent.
22288  */
22289  duk_push_uarridx(ctx, idx_last);
22290  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
22291 
22292  DUK_ASSERT_TOP(ctx, n + 1);
22293  return 1;
22294 }
22295 
22296 /*
22297  * join(), toLocaleString()
22298  *
22299  * Note: checking valstack is necessary, but only in the per-element loop.
22300  *
22301  * Note: the trivial approach of pushing all the elements on the value stack
22302  * and then calling duk_join() fails when the array contains a large number
22303  * of elements. This problem can't be offloaded to duk_join() because the
22304  * elements to join must be handled here and have special handling. Current
22305  * approach is to do intermediate joins with very large number of elements.
22306  * There is no fancy handling; the prefix gets re-joined multiple times.
22307  */
22308 
22309 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx) {
22310  duk_uint32_t len, count;
22311  duk_uint32_t idx;
22312  duk_small_int_t to_locale_string = duk_get_current_magic(ctx);
22313  duk_idx_t valstack_required;
22314 
22315  /* For join(), nargs is 1. For toLocaleString(), nargs is 0 and
22316  * setting the top essentially pushes an undefined to the stack,
22317  * thus defaulting to a comma separator.
22318  */
22319  duk_set_top(ctx, 1);
22320  if (duk_is_undefined(ctx, 0)) {
22321  duk_pop(ctx);
22322  duk_push_hstring_stridx(ctx, DUK_STRIDX_COMMA);
22323  } else {
22324  duk_to_string(ctx, 0);
22325  }
22326 
22327  len = duk__push_this_obj_len_u32(ctx);
22328 
22329  /* [ sep ToObject(this) len ] */
22330 
22331  DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
22332  (duk_tval *) duk_get_tval(ctx, 0),
22333  (duk_tval *) duk_get_tval(ctx, 1),
22334  (unsigned long) len));
22335 
22336  /* The extra (+4) is tight. */
22337  valstack_required = (len >= DUK__ARRAY_MID_JOIN_LIMIT ?
22338  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4;
22339  duk_require_stack(ctx, valstack_required);
22340 
22341  duk_dup_0(ctx);
22342 
22343  /* [ sep ToObject(this) len sep ] */
22344 
22345  count = 0;
22346  idx = 0;
22347  for (;;) {
22348  DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
22349  if (count >= DUK__ARRAY_MID_JOIN_LIMIT || /* intermediate join to avoid valstack overflow */
22350  idx >= len) { /* end of loop (careful with len==0) */
22351  /* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
22352  DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
22353  (long) count, (long) idx, (long) len));
22354  duk_join(ctx, (duk_idx_t) count); /* -> [ sep ToObject(this) len str ] */
22355  duk_dup_0(ctx); /* -> [ sep ToObject(this) len str sep ] */
22356  duk_insert(ctx, -2); /* -> [ sep ToObject(this) len sep str ] */
22357  count = 1;
22358  }
22359  if (idx >= len) {
22360  /* if true, the stack already contains the final result */
22361  break;
22362  }
22363 
22364  duk_get_prop_index(ctx, 1, (duk_uarridx_t) idx);
22365  if (duk_is_null_or_undefined(ctx, -1)) {
22366  duk_pop(ctx);
22367  duk_push_hstring_empty(ctx);
22368  } else {
22369  if (to_locale_string) {
22370  duk_to_object(ctx, -1);
22371  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_TO_LOCALE_STRING);
22372  duk_insert(ctx, -2); /* -> [ ... toLocaleString ToObject(val) ] */
22373  duk_call_method(ctx, 0);
22374  }
22375  duk_to_string(ctx, -1);
22376  }
22377 
22378  count++;
22379  idx++;
22380  }
22381 
22382  /* [ sep ToObject(this) len sep result ] */
22383 
22384  return 1;
22385 }
22386 
22387 /*
22388  * pop(), push()
22389  */
22390 
22391 #if defined(DUK_USE_ARRAY_FASTPATH)
22392 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_context *ctx, duk_harray *h_arr) {
22393  duk_hthread *thr;
22394  duk_tval *tv_arraypart;
22395  duk_tval *tv_val;
22396  duk_uint32_t len;
22397 
22398  thr = (duk_hthread *) ctx;
22399 
22400  tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
22401  len = h_arr->length;
22402  if (len <= 0) {
22403  /* nop, return undefined */
22404  return 0;
22405  }
22406 
22407  len--;
22408  h_arr->length = len;
22409 
22410  /* Fast path doesn't check for an index property inherited from
22411  * Array.prototype. This is quite often acceptable; if not,
22412  * disable fast path.
22413  */
22414  DUK_ASSERT_VS_SPACE(thr);
22415  tv_val = tv_arraypart + len;
22416  if (DUK_TVAL_IS_UNUSED(tv_val)) {
22417  /* No net refcount change. Value stack already has
22418  * 'undefined' based on value stack init policy.
22419  */
22420  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
22421  DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
22422  } else {
22423  /* No net refcount change. */
22424  DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
22425  DUK_TVAL_SET_UNUSED(tv_val);
22426  }
22427  thr->valstack_top++;
22428 
22429  /* XXX: there's no shrink check in the fast path now */
22430 
22431  return 1;
22432 }
22433 #endif /* DUK_USE_ARRAY_FASTPATH */
22434 
22435 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx) {
22436  duk_uint32_t len;
22437  duk_uint32_t idx;
22438 #if defined(DUK_USE_ARRAY_FASTPATH)
22439  duk_harray *h_arr;
22440 #endif
22441 
22442  DUK_ASSERT_TOP(ctx, 0);
22443 
22444 #if defined(DUK_USE_ARRAY_FASTPATH)
22445  h_arr = duk__arraypart_fastpath_this(ctx);
22446  if (h_arr) {
22447  return duk__array_pop_fastpath(ctx, h_arr);
22448  }
22449 #endif
22450 
22451  /* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
22452 
22453  len = duk__push_this_obj_len_u32(ctx);
22454  if (len == 0) {
22455  duk_push_int(ctx, 0);
22456  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LENGTH);
22457  return 0;
22458  }
22459  idx = len - 1;
22460 
22461  duk_get_prop_index(ctx, 0, (duk_uarridx_t) idx);
22462  duk_del_prop_index(ctx, 0, (duk_uarridx_t) idx);
22463  duk_push_u32(ctx, idx);
22464  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LENGTH);
22465  return 1;
22466 }
22467 
22468 #if defined(DUK_USE_ARRAY_FASTPATH)
22469 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_context *ctx, duk_harray *h_arr) {
22470  duk_hthread *thr;
22471  duk_tval *tv_arraypart;
22472  duk_tval *tv_src;
22473  duk_tval *tv_dst;
22474  duk_uint32_t len;
22475  duk_idx_t i, n;
22476 
22477  thr = (duk_hthread *) ctx;
22478 
22479  len = h_arr->length;
22480  tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
22481 
22482  n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22483  if (DUK_UNLIKELY(len + n < len)) {
22484  DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
22485  DUK_DCERROR_RANGE_INVALID_LENGTH(thr); /* != 0 return value returned as is by caller */
22486  }
22487  if (len + n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
22488  /* Array part would need to be extended. Rely on slow path
22489  * for now.
22490  *
22491  * XXX: Rework hobject code a bit and add extend support.
22492  */
22493  return 0;
22494  }
22495 
22496  tv_src = thr->valstack_bottom;
22497  tv_dst = tv_arraypart + len;
22498  for (i = 0; i < n; i++) {
22499  /* No net refcount change; reset value stack values to
22500  * undefined to satisfy value stack init policy.
22501  */
22502  DUK_TVAL_SET_TVAL(tv_dst, tv_src);
22503  DUK_TVAL_SET_UNDEFINED(tv_src);
22504  tv_src++;
22505  tv_dst++;
22506  }
22507  thr->valstack_top = thr->valstack_bottom;
22508  len += n;
22509  h_arr->length = len;
22510 
22511  DUK_ASSERT((duk_uint_t) len == len);
22512  duk_push_uint(ctx, (duk_uint_t) len);
22513  return 1;
22514 }
22515 #endif /* DUK_USE_ARRAY_FASTPATH */
22516 
22517 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx) {
22518  /* Note: 'this' is not necessarily an Array object. The push()
22519  * algorithm is supposed to work for other kinds of objects too,
22520  * so the algorithm has e.g. an explicit update for the 'length'
22521  * property which is normally "magical" in arrays.
22522  */
22523 
22524  duk_uint32_t len;
22525  duk_idx_t i, n;
22526 #if defined(DUK_USE_ARRAY_FASTPATH)
22527  duk_harray *h_arr;
22528 #endif
22529 
22530 #if defined(DUK_USE_ARRAY_FASTPATH)
22531  h_arr = duk__arraypart_fastpath_this(ctx);
22532  if (h_arr) {
22533  duk_ret_t rc;
22534  rc = duk__array_push_fastpath(ctx, h_arr);
22535  if (rc != 0) {
22536  return rc;
22537  }
22538  DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
22539  }
22540 #endif
22541 
22542  n = duk_get_top(ctx);
22543  len = duk__push_this_obj_len_u32(ctx);
22544 
22545  /* [ arg1 ... argN obj length ] */
22546 
22547  /* Technically Array.prototype.push() can create an Array with length
22548  * longer than 2^32-1, i.e. outside the 32-bit range. The final length
22549  * is *not* wrapped to 32 bits in the specification.
22550  *
22551  * This implementation tracks length with a uint32 because it's much
22552  * more practical.
22553  *
22554  * See: test-bi-array-push-maxlen.js.
22555  */
22556 
22557  if (len + (duk_uint32_t) n < len) {
22558  DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
22559  DUK_DCERROR_RANGE_INVALID_LENGTH((duk_hthread *) ctx);
22560  }
22561 
22562  for (i = 0; i < n; i++) {
22563  duk_dup(ctx, i);
22564  duk_put_prop_index(ctx, -3, len + i);
22565  }
22566  len += n;
22567 
22568  duk_push_u32(ctx, len);
22569  duk_dup_top(ctx);
22570  duk_put_prop_stridx_short(ctx, -4, DUK_STRIDX_LENGTH);
22571 
22572  /* [ arg1 ... argN obj length new_length ] */
22573  return 1;
22574 }
22575 
22576 /*
22577  * sort()
22578  *
22579  * Currently qsort with random pivot. This is now really, really slow,
22580  * because there is no fast path for array parts.
22581  *
22582  * Signed indices are used because qsort() leaves and degenerate cases
22583  * may use a negative offset.
22584  */
22585 
22586 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_context *ctx, duk_int_t idx1, duk_int_t idx2) {
22587  duk_bool_t have1, have2;
22588  duk_bool_t undef1, undef2;
22589  duk_small_int_t ret;
22590  duk_idx_t idx_obj = 1; /* fixed offsets in valstack */
22591  duk_idx_t idx_fn = 0;
22592  duk_hstring *h1, *h2;
22593 
22594  /* Fast exit if indices are identical. This is valid for a non-existent property,
22595  * for an undefined value, and almost always for ToString() coerced comparison of
22596  * arbitrary values (corner cases where this is not the case include e.g. a an
22597  * object with varying ToString() coercion).
22598  *
22599  * The specification does not prohibit "caching" of values read from the array, so
22600  * assuming equality for comparing an index with itself falls into the category of
22601  * "caching".
22602  *
22603  * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
22604  * have an effect on the final result. The specification does not require any
22605  * specific behavior for inconsistent compare functions, so again, this fast path
22606  * is OK.
22607  */
22608 
22609  if (idx1 == idx2) {
22610  DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
22611  (long) idx1, (long) idx2));
22612  return 0;
22613  }
22614 
22615  have1 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx1);
22616  have2 = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) idx2);
22617 
22618  DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
22619  (long) idx1, (long) idx2, (long) have1, (long) have2,
22620  (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
22621 
22622  if (have1) {
22623  if (have2) {
22624  ;
22625  } else {
22626  ret = -1;
22627  goto pop_ret;
22628  }
22629  } else {
22630  if (have2) {
22631  ret = 1;
22632  goto pop_ret;
22633  } else {
22634  ret = 0;
22635  goto pop_ret;
22636  }
22637  }
22638 
22639  undef1 = duk_is_undefined(ctx, -2);
22640  undef2 = duk_is_undefined(ctx, -1);
22641  if (undef1) {
22642  if (undef2) {
22643  ret = 0;
22644  goto pop_ret;
22645  } else {
22646  ret = 1;
22647  goto pop_ret;
22648  }
22649  } else {
22650  if (undef2) {
22651  ret = -1;
22652  goto pop_ret;
22653  } else {
22654  ;
22655  }
22656  }
22657 
22658  if (!duk_is_undefined(ctx, idx_fn)) {
22659  duk_double_t d;
22660 
22661  /* No need to check callable; duk_call() will do that. */
22662  duk_dup(ctx, idx_fn); /* -> [ ... x y fn ] */
22663  duk_insert(ctx, -3); /* -> [ ... fn x y ] */
22664  duk_call(ctx, 2); /* -> [ ... res ] */
22665 
22666  /* ES5 is a bit vague about what to do if the return value is
22667  * not a number. ES2015 provides a concrete description:
22668  * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
22669  */
22670 
22671  d = duk_to_number_m1(ctx);
22672  if (d < 0.0) {
22673  ret = -1;
22674  } else if (d > 0.0) {
22675  ret = 1;
22676  } else {
22677  /* Because NaN compares to false, NaN is handled here
22678  * without an explicit check above.
22679  */
22680  ret = 0;
22681  }
22682 
22683  duk_pop(ctx);
22684  DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
22685  return ret;
22686  }
22687 
22688  /* string compare is the default (a bit oddly) */
22689 
22690  /* XXX: any special handling for plain array; causes repeated coercion now? */
22691  h1 = duk_to_hstring(ctx, -2);
22692  h2 = duk_to_hstring_m1(ctx);
22693  DUK_ASSERT(h1 != NULL);
22694  DUK_ASSERT(h2 != NULL);
22695 
22696  ret = duk_js_string_compare(h1, h2); /* retval is directly usable */
22697  goto pop_ret;
22698 
22699  pop_ret:
22700  duk_pop_2(ctx);
22701  DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
22702  return ret;
22703 }
22704 
22705 DUK_LOCAL void duk__array_sort_swap(duk_context *ctx, duk_int_t l, duk_int_t r) {
22706  duk_bool_t have_l, have_r;
22707  duk_idx_t idx_obj = 1; /* fixed offset in valstack */
22708 
22709  if (l == r) {
22710  return;
22711  }
22712 
22713  /* swap elements; deal with non-existent elements correctly */
22714  have_l = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
22715  have_r = duk_get_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
22716 
22717  if (have_r) {
22718  /* right exists, [[Put]] regardless whether or not left exists */
22719  duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
22720  } else {
22721  duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) l);
22722  duk_pop(ctx);
22723  }
22724 
22725  if (have_l) {
22726  duk_put_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
22727  } else {
22728  duk_del_prop_index(ctx, idx_obj, (duk_uarridx_t) r);
22729  duk_pop(ctx);
22730  }
22731 }
22732 
22733 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
22734 /* Debug print which visualizes the qsort partitioning process. */
22735 DUK_LOCAL void duk__debuglog_qsort_state(duk_context *ctx, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
22736  char buf[4096];
22737  char *ptr = buf;
22738  duk_int_t i, n;
22739  n = (duk_int_t) duk_get_length(ctx, 1);
22740  if (n > 4000) {
22741  n = 4000;
22742  }
22743  *ptr++ = '[';
22744  for (i = 0; i < n; i++) {
22745  if (i == pivot) {
22746  *ptr++ = '|';
22747  } else if (i == lo) {
22748  *ptr++ = '<';
22749  } else if (i == hi) {
22750  *ptr++ = '>';
22751  } else if (i >= lo && i <= hi) {
22752  *ptr++ = '-';
22753  } else {
22754  *ptr++ = ' ';
22755  }
22756  }
22757  *ptr++ = ']';
22758  *ptr++ = '\0';
22759 
22760  DUK_DDD(DUK_DDDPRINT("%s (lo=%ld, hi=%ld, pivot=%ld)",
22761  (const char *) buf, (long) lo, (long) hi, (long) pivot));
22762 }
22763 #endif
22764 
22765 DUK_LOCAL void duk__array_qsort(duk_context *ctx, duk_int_t lo, duk_int_t hi) {
22766  duk_int_t p, l, r;
22767 
22768  /* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
22769 
22770  DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
22771  (long) lo, (long) hi, (duk_tval *) duk_get_tval(ctx, 1)));
22772 
22773  DUK_ASSERT_TOP(ctx, 3);
22774 
22775  /* In some cases it may be that lo > hi, or hi < 0; these
22776  * degenerate cases happen e.g. for empty arrays, and in
22777  * recursion leaves.
22778  */
22779 
22780  /* trivial cases */
22781  if (hi - lo < 1) {
22782  DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
22783  return;
22784  }
22785  DUK_ASSERT(hi > lo);
22786  DUK_ASSERT(hi - lo + 1 >= 2);
22787 
22788  /* randomized pivot selection */
22789  p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE((duk_hthread *) ctx) * (duk_double_t) (hi - lo + 1));
22790  DUK_ASSERT(p >= lo && p <= hi);
22791  DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
22792 
22793  /* move pivot out of the way */
22794  duk__array_sort_swap(ctx, p, lo);
22795  p = lo;
22796  DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
22797 
22798  l = lo + 1;
22799  r = hi;
22800  for (;;) {
22801  /* find elements to swap */
22802  for (;;) {
22803  DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
22804  (long) l, (long) r, (long) p));
22805  if (l >= hi) {
22806  break;
22807  }
22808  if (duk__array_sort_compare(ctx, l, p) >= 0) { /* !(l < p) */
22809  break;
22810  }
22811  l++;
22812  }
22813  for (;;) {
22814  DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
22815  (long) l, (long) r, (long) p));
22816  if (r <= lo) {
22817  break;
22818  }
22819  if (duk__array_sort_compare(ctx, p, r) >= 0) { /* !(p < r) */
22820  break;
22821  }
22822  r--;
22823  }
22824  if (l >= r) {
22825  goto done;
22826  }
22827  DUK_ASSERT(l < r);
22828 
22829  DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
22830 
22831  duk__array_sort_swap(ctx, l, r);
22832 
22833  DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
22834  l++;
22835  r--;
22836  }
22837  done:
22838  /* Note that 'l' and 'r' may cross, i.e. r < l */
22839  DUK_ASSERT(l >= lo && l <= hi);
22840  DUK_ASSERT(r >= lo && r <= hi);
22841 
22842  /* XXX: there's no explicit recursion bound here now. For the average
22843  * qsort recursion depth O(log n) that's not really necessary: e.g. for
22844  * 2**32 recursion depth would be about 32 which is OK. However, qsort
22845  * worst case recursion depth is O(n) which may be a problem.
22846  */
22847 
22848  /* move pivot to its final place */
22849  DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(ctx, 1)));
22850  duk__array_sort_swap(ctx, lo, r);
22851 
22852 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
22853  duk__debuglog_qsort_state(ctx, lo, hi, r);
22854 #endif
22855 
22856  DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(ctx, 1)));
22857  duk__array_qsort(ctx, lo, r - 1);
22858  duk__array_qsort(ctx, r + 1, hi);
22859 }
22860 
22861 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx) {
22862  duk_uint32_t len;
22863 
22864  /* XXX: len >= 0x80000000 won't work below because a signed type
22865  * is needed by qsort.
22866  */
22867  len = duk__push_this_obj_len_u32_limited(ctx);
22868 
22869  /* stack[0] = compareFn
22870  * stack[1] = ToObject(this)
22871  * stack[2] = ToUint32(length)
22872  */
22873 
22874  if (len > 0) {
22875  /* avoid degenerate cases, so that (len - 1) won't underflow */
22876  duk__array_qsort(ctx, (duk_int_t) 0, (duk_int_t) (len - 1));
22877  }
22878 
22879  DUK_ASSERT_TOP(ctx, 3);
22880  duk_pop(ctx);
22881  return 1; /* return ToObject(this) */
22882 }
22883 
22884 /*
22885  * splice()
22886  */
22887 
22888 /* XXX: this compiles to over 500 bytes now, even without special handling
22889  * for an array part. Uses signed ints so does not handle full array range correctly.
22890  */
22891 
22892 /* XXX: can shift() / unshift() use the same helper?
22893  * shift() is (close to?) <--> splice(0, 1)
22894  * unshift is (close to?) <--> splice(0, 0, [items])?
22895  */
22896 
22897 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx) {
22898  duk_idx_t nargs;
22899  duk_uint32_t len;
22900  duk_bool_t have_delcount;
22901  duk_int_t item_count;
22902  duk_int_t act_start;
22903  duk_int_t del_count;
22904  duk_int_t i, n;
22905 
22906  DUK_UNREF(have_delcount);
22907 
22908  nargs = duk_get_top(ctx);
22909  if (nargs < 2) {
22910  duk_set_top(ctx, 2);
22911  nargs = 2;
22912  have_delcount = 0;
22913  } else {
22914  have_delcount = 1;
22915  }
22916 
22917  /* XXX: len >= 0x80000000 won't work below because we need to be
22918  * able to represent -len.
22919  */
22920  len = duk__push_this_obj_len_u32_limited(ctx);
22921 
22922  act_start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
22923  if (act_start < 0) {
22924  act_start = len + act_start;
22925  }
22926  DUK_ASSERT(act_start >= 0 && act_start <= (duk_int_t) len);
22927 
22928 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
22929  if (have_delcount) {
22930 #endif
22931  del_count = duk_to_int_clamped(ctx, 1, 0, len - act_start);
22932 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
22933  } else {
22934  /* E5.1 standard behavior when deleteCount is not given would be
22935  * to treat it just like if 'undefined' was given, which coerces
22936  * ultimately to 0. Real world behavior is to splice to the end
22937  * of array, see test-bi-array-proto-splice-no-delcount.js.
22938  */
22939  del_count = len - act_start;
22940  }
22941 #endif
22942 
22943  DUK_ASSERT(nargs >= 2);
22944  item_count = (duk_int_t) (nargs - 2);
22945 
22946  DUK_ASSERT(del_count >= 0 && del_count <= (duk_int_t) len - act_start);
22947  DUK_ASSERT(del_count + act_start <= (duk_int_t) len);
22948 
22949  /* For now, restrict result array into 32-bit length range. */
22950  if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
22951  DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
22952  DUK_DCERROR_RANGE_INVALID_LENGTH((duk_hthread *) ctx);
22953  }
22954 
22955  duk_push_array(ctx);
22956 
22957  /* stack[0] = start
22958  * stack[1] = deleteCount
22959  * stack[2...nargs-1] = items
22960  * stack[nargs] = ToObject(this) -3
22961  * stack[nargs+1] = ToUint32(length) -2
22962  * stack[nargs+2] = result array -1
22963  */
22964 
22965  DUK_ASSERT_TOP(ctx, nargs + 3);
22966 
22967  /* Step 9: copy elements-to-be-deleted into the result array */
22968 
22969  for (i = 0; i < del_count; i++) {
22970  if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (act_start + i))) {
22971  duk_xdef_prop_index_wec(ctx, -2, i); /* throw flag irrelevant (false in std alg) */
22972  } else {
22973  duk_pop(ctx);
22974  }
22975  }
22976  duk_push_u32(ctx, (duk_uint32_t) del_count);
22977  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
22978 
22979  /* Steps 12 and 13: reorganize elements to make room for itemCount elements */
22980 
22981  if (item_count < del_count) {
22982  /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 1
22983  * -> [ A B F G H ] (conceptual intermediate step)
22984  * -> [ A B . F G H ] (placeholder marked)
22985  * [ A B C F G H ] (actual result at this point, C will be replaced)
22986  */
22987 
22988  DUK_ASSERT_TOP(ctx, nargs + 3);
22989 
22990  n = len - del_count;
22991  for (i = act_start; i < n; i++) {
22992  if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
22993  duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
22994  } else {
22995  duk_pop(ctx);
22996  duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
22997  }
22998  }
22999 
23000  DUK_ASSERT_TOP(ctx, nargs + 3);
23001 
23002  /* loop iterator init and limit changed from standard algorithm */
23003  n = len - del_count + item_count;
23004  for (i = len - 1; i >= n; i--) {
23005  duk_del_prop_index(ctx, -3, (duk_uarridx_t) i);
23006  }
23007 
23008  DUK_ASSERT_TOP(ctx, nargs + 3);
23009  } else if (item_count > del_count) {
23010  /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 4
23011  * -> [ A B F G H ] (conceptual intermediate step)
23012  * -> [ A B . . . . F G H ] (placeholder marked)
23013  * [ A B C D E F F G H ] (actual result at this point)
23014  */
23015 
23016  DUK_ASSERT_TOP(ctx, nargs + 3);
23017 
23018  /* loop iterator init and limit changed from standard algorithm */
23019  for (i = len - del_count - 1; i >= act_start; i--) {
23020  if (duk_get_prop_index(ctx, -3, (duk_uarridx_t) (i + del_count))) {
23021  duk_put_prop_index(ctx, -4, (duk_uarridx_t) (i + item_count));
23022  } else {
23023  duk_pop(ctx);
23024  duk_del_prop_index(ctx, -3, (duk_uarridx_t) (i + item_count));
23025  }
23026  }
23027 
23028  DUK_ASSERT_TOP(ctx, nargs + 3);
23029  } else {
23030  /* [ A B C D E F G H ] rel_index = 2, del_count 3, item count 3
23031  * -> [ A B F G H ] (conceptual intermediate step)
23032  * -> [ A B . . . F G H ] (placeholder marked)
23033  * [ A B C D E F G H ] (actual result at this point)
23034  */
23035  }
23036  DUK_ASSERT_TOP(ctx, nargs + 3);
23037 
23038  /* Step 15: insert itemCount elements into the hole made above */
23039 
23040  for (i = 0; i < item_count; i++) {
23041  duk_dup(ctx, i + 2); /* args start at index 2 */
23042  duk_put_prop_index(ctx, -4, (duk_uarridx_t) (act_start + i));
23043  }
23044 
23045  /* Step 16: update length; note that the final length may be above 32 bit range
23046  * (but we checked above that this isn't the case here)
23047  */
23048 
23049  duk_push_u32(ctx, len - del_count + item_count);
23050  duk_put_prop_stridx_short(ctx, -4, DUK_STRIDX_LENGTH);
23051 
23052  /* result array is already at the top of stack */
23053  DUK_ASSERT_TOP(ctx, nargs + 3);
23054  return 1;
23055 }
23056 
23057 /*
23058  * reverse()
23059  */
23060 
23061 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx) {
23062  duk_uint32_t len;
23063  duk_uint32_t middle;
23064  duk_uint32_t lower, upper;
23065  duk_bool_t have_lower, have_upper;
23066 
23067  len = duk__push_this_obj_len_u32(ctx);
23068  middle = len / 2;
23069 
23070  /* If len <= 1, middle will be 0 and for-loop bails out
23071  * immediately (0 < 0 -> false).
23072  */
23073 
23074  for (lower = 0; lower < middle; lower++) {
23075  DUK_ASSERT(len >= 2);
23076  DUK_ASSERT_TOP(ctx, 2);
23077 
23078  DUK_ASSERT(len >= lower + 1);
23079  upper = len - lower - 1;
23080 
23081  have_lower = duk_get_prop_index(ctx, -2, (duk_uarridx_t) lower);
23082  have_upper = duk_get_prop_index(ctx, -3, (duk_uarridx_t) upper);
23083 
23084  /* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
23085 
23086  if (have_upper) {
23087  duk_put_prop_index(ctx, -4, (duk_uarridx_t) lower);
23088  } else {
23089  duk_del_prop_index(ctx, -4, (duk_uarridx_t) lower);
23090  duk_pop(ctx);
23091  }
23092 
23093  if (have_lower) {
23094  duk_put_prop_index(ctx, -3, (duk_uarridx_t) upper);
23095  } else {
23096  duk_del_prop_index(ctx, -3, (duk_uarridx_t) upper);
23097  duk_pop(ctx);
23098  }
23099 
23100  DUK_ASSERT_TOP(ctx, 2);
23101  }
23102 
23103  DUK_ASSERT_TOP(ctx, 2);
23104  duk_pop(ctx); /* -> [ ToObject(this) ] */
23105  return 1;
23106 }
23107 
23108 /*
23109  * slice()
23110  */
23111 
23112 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx) {
23113  duk_uint32_t len;
23114  duk_int_t start, end;
23115  duk_int_t i;
23116  duk_uarridx_t idx;
23117  duk_uint32_t res_length = 0;
23118 
23119  /* XXX: len >= 0x80000000 won't work below because we need to be
23120  * able to represent -len.
23121  */
23122  len = duk__push_this_obj_len_u32_limited(ctx);
23123  duk_push_array(ctx);
23124 
23125  /* stack[0] = start
23126  * stack[1] = end
23127  * stack[2] = ToObject(this)
23128  * stack[3] = ToUint32(length)
23129  * stack[4] = result array
23130  */
23131 
23132  start = duk_to_int_clamped(ctx, 0, -((duk_int_t) len), (duk_int_t) len);
23133  if (start < 0) {
23134  start = len + start;
23135  }
23136  /* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
23137  * (the upper limit)?
23138  */
23139  if (duk_is_undefined(ctx, 1)) {
23140  end = len;
23141  } else {
23142  end = duk_to_int_clamped(ctx, 1, -((duk_int_t) len), (duk_int_t) len);
23143  if (end < 0) {
23144  end = len + end;
23145  }
23146  }
23147  DUK_ASSERT(start >= 0 && (duk_uint32_t) start <= len);
23148  DUK_ASSERT(end >= 0 && (duk_uint32_t) end <= len);
23149 
23150  idx = 0;
23151  for (i = start; i < end; i++) {
23152  DUK_ASSERT_TOP(ctx, 5);
23153  if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
23154  duk_xdef_prop_index_wec(ctx, 4, idx);
23155  res_length = idx + 1;
23156  } else {
23157  duk_pop(ctx);
23158  }
23159  idx++;
23160  DUK_ASSERT_TOP(ctx, 5);
23161  }
23162 
23163  duk_push_u32(ctx, res_length);
23164  duk_xdef_prop_stridx_short(ctx, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
23165 
23166  DUK_ASSERT_TOP(ctx, 5);
23167  return 1;
23168 }
23169 
23170 /*
23171  * shift()
23172  */
23173 
23174 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx) {
23175  duk_uint32_t len;
23176  duk_uint32_t i;
23177 
23178  len = duk__push_this_obj_len_u32(ctx);
23179  if (len == 0) {
23180  duk_push_int(ctx, 0);
23181  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LENGTH);
23182  return 0;
23183  }
23184 
23185  duk_get_prop_index(ctx, 0, 0);
23186 
23187  /* stack[0] = object (this)
23188  * stack[1] = ToUint32(length)
23189  * stack[2] = elem at index 0 (retval)
23190  */
23191 
23192  for (i = 1; i < len; i++) {
23193  DUK_ASSERT_TOP(ctx, 3);
23194  if (duk_get_prop_index(ctx, 0, (duk_uarridx_t) i)) {
23195  /* fromPresent = true */
23196  duk_put_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
23197  } else {
23198  /* fromPresent = false */
23199  duk_del_prop_index(ctx, 0, (duk_uarridx_t) (i - 1));
23200  duk_pop(ctx);
23201  }
23202  }
23203  duk_del_prop_index(ctx, 0, (duk_uarridx_t) (len - 1));
23204 
23205  duk_push_u32(ctx, (duk_uint32_t) (len - 1));
23206  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LENGTH);
23207 
23208  DUK_ASSERT_TOP(ctx, 3);
23209  return 1;
23210 }
23211 
23212 /*
23213  * unshift()
23214  */
23215 
23216 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx) {
23217  duk_idx_t nargs;
23218  duk_uint32_t len;
23219  duk_uint32_t i;
23220 
23221  nargs = duk_get_top(ctx);
23222  len = duk__push_this_obj_len_u32(ctx);
23223 
23224  /* stack[0...nargs-1] = unshift args (vararg)
23225  * stack[nargs] = ToObject(this)
23226  * stack[nargs+1] = ToUint32(length)
23227  */
23228 
23229  DUK_ASSERT_TOP(ctx, nargs + 2);
23230 
23231  /* Note: unshift() may operate on indices above unsigned 32-bit range
23232  * and the final length may be >= 2**32. However, we restrict the
23233  * final result to 32-bit range for practicality.
23234  */
23235 
23236  if (len + (duk_uint32_t) nargs < len) {
23237  DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
23238  DUK_DCERROR_RANGE_INVALID_LENGTH((duk_hthread *) ctx);
23239  }
23240 
23241  i = len;
23242  while (i > 0) {
23243  DUK_ASSERT_TOP(ctx, nargs + 2);
23244  i--;
23245  /* k+argCount-1; note that may be above 32-bit range */
23246 
23247  if (duk_get_prop_index(ctx, -2, (duk_uarridx_t) i)) {
23248  /* fromPresent = true */
23249  /* [ ... ToObject(this) ToUint32(length) val ] */
23250  duk_put_prop_index(ctx, -3, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
23251  } else {
23252  /* fromPresent = false */
23253  /* [ ... ToObject(this) ToUint32(length) val ] */
23254  duk_pop(ctx);
23255  duk_del_prop_index(ctx, -2, (duk_uarridx_t) (i + nargs)); /* -> [ ... ToObject(this) ToUint32(length) ] */
23256  }
23257  DUK_ASSERT_TOP(ctx, nargs + 2);
23258  }
23259 
23260  for (i = 0; i < (duk_uint32_t) nargs; i++) {
23261  DUK_ASSERT_TOP(ctx, nargs + 2);
23262  duk_dup(ctx, i); /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
23263  duk_put_prop_index(ctx, -3, (duk_uarridx_t) i);
23264  DUK_ASSERT_TOP(ctx, nargs + 2);
23265  }
23266 
23267  DUK_ASSERT_TOP(ctx, nargs + 2);
23268  duk_push_u32(ctx, len + nargs);
23269  duk_dup_top(ctx); /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
23270  duk_put_prop_stridx_short(ctx, -4, DUK_STRIDX_LENGTH);
23271  return 1;
23272 }
23273 
23274 /*
23275  * indexOf(), lastIndexOf()
23276  */
23277 
23278 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx) {
23279  duk_idx_t nargs;
23280  duk_int_t i, len;
23281  duk_int_t from_idx;
23282  duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for indexOf, -1 for lastIndexOf */
23283 
23284  /* lastIndexOf() needs to be a vararg function because we must distinguish
23285  * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
23286  * made vararg for symmetry although it doesn't strictly need to be.
23287  */
23288 
23289  nargs = duk_get_top(ctx);
23290  duk_set_top(ctx, 2);
23291 
23292  /* XXX: must be able to represent -len */
23293  len = (duk_int_t) duk__push_this_obj_len_u32_limited(ctx);
23294  if (len == 0) {
23295  goto not_found;
23296  }
23297 
23298  /* Index clamping is a bit tricky, we must ensure that we'll only iterate
23299  * through elements that exist and that the specific requirements from E5.1
23300  * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
23301  *
23302  * - indexOf: clamp to [-len,len], negative handling -> [0,len],
23303  * if clamped result is len, for-loop bails out immediately
23304  *
23305  * - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
23306  * if clamped result is -1, for-loop bails out immediately
23307  *
23308  * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
23309  * for indexOf() but incorrect for lastIndexOf(). Hence special handling,
23310  * and why lastIndexOf() needs to be a vararg function.
23311  */
23312 
23313  if (nargs >= 2) {
23314  /* indexOf: clamp fromIndex to [-len, len]
23315  * (if fromIndex == len, for-loop terminates directly)
23316  *
23317  * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
23318  * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
23319  */
23320  from_idx = duk_to_int_clamped(ctx,
23321  1,
23322  (idx_step > 0 ? -len : -len - 1),
23323  (idx_step > 0 ? len : len - 1));
23324  if (from_idx < 0) {
23325  /* for lastIndexOf, result may be -1 (mark immediate termination) */
23326  from_idx = len + from_idx;
23327  }
23328  } else {
23329  /* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
23330  * handle both indexOf and lastIndexOf specially here.
23331  */
23332  if (idx_step > 0) {
23333  from_idx = 0;
23334  } else {
23335  from_idx = len - 1;
23336  }
23337  }
23338 
23339  /* stack[0] = searchElement
23340  * stack[1] = fromIndex
23341  * stack[2] = object
23342  * stack[3] = length (not needed, but not popped above)
23343  */
23344 
23345  for (i = from_idx; i >= 0 && i < len; i += idx_step) {
23346  DUK_ASSERT_TOP(ctx, 4);
23347 
23348  if (duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
23349  DUK_ASSERT_TOP(ctx, 5);
23350  if (duk_strict_equals(ctx, 0, 4)) {
23351  duk_push_int(ctx, i);
23352  return 1;
23353  }
23354  }
23355 
23356  duk_pop(ctx);
23357  }
23358 
23359  not_found:
23360  duk_push_int(ctx, -1);
23361  return 1;
23362 }
23363 
23364 /*
23365  * every(), some(), forEach(), map(), filter()
23366  */
23367 
23368 #define DUK__ITER_EVERY 0
23369 #define DUK__ITER_SOME 1
23370 #define DUK__ITER_FOREACH 2
23371 #define DUK__ITER_MAP 3
23372 #define DUK__ITER_FILTER 4
23373 
23374 /* XXX: This helper is a bit awkward because the handling for the different iteration
23375  * callers is quite different. This now compiles to a bit less than 500 bytes, so with
23376  * 5 callers the net result is about 100 bytes / caller.
23377  */
23378 
23379 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx) {
23380  duk_uint32_t len;
23381  duk_uint32_t i;
23382  duk_uarridx_t k;
23383  duk_bool_t bval;
23384  duk_small_int_t iter_type = duk_get_current_magic(ctx);
23385  duk_uint32_t res_length = 0;
23386 
23387  /* each call this helper serves has nargs==2 */
23388  DUK_ASSERT_TOP(ctx, 2);
23389 
23390  len = duk__push_this_obj_len_u32(ctx);
23391  duk_require_callable(ctx, 0);
23392  /* if thisArg not supplied, behave as if undefined was supplied */
23393 
23394  if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
23395  duk_push_array(ctx);
23396  } else {
23397  duk_push_undefined(ctx);
23398  }
23399 
23400  /* stack[0] = callback
23401  * stack[1] = thisArg
23402  * stack[2] = object
23403  * stack[3] = ToUint32(length) (unused, but avoid unnecessary pop)
23404  * stack[4] = result array (or undefined)
23405  */
23406 
23407  k = 0; /* result index for filter() */
23408  for (i = 0; i < len; i++) {
23409  DUK_ASSERT_TOP(ctx, 5);
23410 
23411  if (!duk_get_prop_index(ctx, 2, (duk_uarridx_t) i)) {
23412 #if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)
23413  /* Real world behavior for map(): trailing non-existent
23414  * elements don't invoke the user callback, but are still
23415  * counted towards result 'length'.
23416  */
23417  if (iter_type == DUK__ITER_MAP) {
23418  res_length = i + 1;
23419  }
23420 #else
23421  /* Standard behavior for map(): trailing non-existent
23422  * elements don't invoke the user callback and are not
23423  * counted towards result 'length'.
23424  */
23425 #endif
23426  duk_pop(ctx);
23427  continue;
23428  }
23429 
23430  /* The original value needs to be preserved for filter(), hence
23431  * this funny order. We can't re-get the value because of side
23432  * effects.
23433  */
23434 
23435  duk_dup_0(ctx);
23436  duk_dup_1(ctx);
23437  duk_dup_m3(ctx);
23438  duk_push_u32(ctx, i);
23439  duk_dup_2(ctx); /* [ ... val callback thisArg val i obj ] */
23440  duk_call_method(ctx, 3); /* -> [ ... val retval ] */
23441 
23442  switch (iter_type) {
23443  case DUK__ITER_EVERY:
23444  bval = duk_to_boolean(ctx, -1);
23445  if (!bval) {
23446  /* stack top contains 'false' */
23447  return 1;
23448  }
23449  break;
23450  case DUK__ITER_SOME:
23451  bval = duk_to_boolean(ctx, -1);
23452  if (bval) {
23453  /* stack top contains 'true' */
23454  return 1;
23455  }
23456  break;
23457  case DUK__ITER_FOREACH:
23458  /* nop */
23459  break;
23460  case DUK__ITER_MAP:
23461  duk_dup_top(ctx);
23462  duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) i); /* retval to result[i] */
23463  res_length = i + 1;
23464  break;
23465  case DUK__ITER_FILTER:
23466  bval = duk_to_boolean(ctx, -1);
23467  if (bval) {
23468  duk_dup_m2(ctx); /* orig value */
23469  duk_xdef_prop_index_wec(ctx, 4, (duk_uarridx_t) k);
23470  k++;
23471  res_length = k;
23472  }
23473  break;
23474  default:
23475  DUK_UNREACHABLE();
23476  break;
23477  }
23478  duk_pop_2(ctx);
23479 
23480  DUK_ASSERT_TOP(ctx, 5);
23481  }
23482 
23483  switch (iter_type) {
23484  case DUK__ITER_EVERY:
23485  duk_push_true(ctx);
23486  break;
23487  case DUK__ITER_SOME:
23488  duk_push_false(ctx);
23489  break;
23490  case DUK__ITER_FOREACH:
23491  duk_push_undefined(ctx);
23492  break;
23493  case DUK__ITER_MAP:
23494  case DUK__ITER_FILTER:
23495  DUK_ASSERT_TOP(ctx, 5);
23496  DUK_ASSERT(duk_is_array(ctx, -1)); /* topmost element is the result array already */
23497  duk_push_u32(ctx, res_length);
23498  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
23499  break;
23500  default:
23501  DUK_UNREACHABLE();
23502  break;
23503  }
23504 
23505  return 1;
23506 }
23507 
23508 /*
23509  * reduce(), reduceRight()
23510  */
23511 
23512 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx) {
23513  duk_idx_t nargs;
23514  duk_bool_t have_acc;
23515  duk_uint32_t i, len;
23516  duk_small_int_t idx_step = duk_get_current_magic(ctx); /* idx_step is +1 for reduce, -1 for reduceRight */
23517 
23518  /* We're a varargs function because we need to detect whether
23519  * initialValue was given or not.
23520  */
23521  nargs = duk_get_top(ctx);
23522  DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
23523 
23524  duk_set_top(ctx, 2);
23525  len = duk__push_this_obj_len_u32(ctx);
23526  duk_require_callable(ctx, 0);
23527 
23528  /* stack[0] = callback fn
23529  * stack[1] = initialValue
23530  * stack[2] = object (coerced this)
23531  * stack[3] = length (not needed, but not popped above)
23532  * stack[4] = accumulator
23533  */
23534 
23535  have_acc = 0;
23536  if (nargs >= 2) {
23537  duk_dup_1(ctx);
23538  have_acc = 1;
23539  }
23540  DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
23541  (long) have_acc, (duk_tval *) duk_get_tval(ctx, 3)));
23542 
23543  /* For len == 0, i is initialized to len - 1 which underflows.
23544  * The condition (i < len) will then exit the for-loop on the
23545  * first round which is correct. Similarly, loop termination
23546  * happens by i underflowing.
23547  */
23548 
23549  for (i = (idx_step >= 0 ? 0 : len - 1);
23550  i < len; /* i >= 0 would always be true */
23551  i += idx_step) {
23552  DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
23553  (long) i, (long) len, (long) have_acc,
23554  (long) duk_get_top(ctx),
23555  (duk_tval *) duk_get_tval(ctx, 4)));
23556 
23557  DUK_ASSERT((have_acc && duk_get_top(ctx) == 5) ||
23558  (!have_acc && duk_get_top(ctx) == 4));
23559 
23560  if (!duk_has_prop_index(ctx, 2, (duk_uarridx_t) i)) {
23561  continue;
23562  }
23563 
23564  if (!have_acc) {
23565  DUK_ASSERT_TOP(ctx, 4);
23566  duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
23567  have_acc = 1;
23568  DUK_ASSERT_TOP(ctx, 5);
23569  } else {
23570  DUK_ASSERT_TOP(ctx, 5);
23571  duk_dup_0(ctx);
23572  duk_dup(ctx, 4);
23573  duk_get_prop_index(ctx, 2, (duk_uarridx_t) i);
23574  duk_push_u32(ctx, i);
23575  duk_dup_2(ctx);
23576  DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
23577  (duk_tval *) duk_get_tval(ctx, -5), (duk_tval *) duk_get_tval(ctx, -4),
23578  (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
23579  (duk_tval *) duk_get_tval(ctx, -1)));
23580  duk_call(ctx, 4);
23581  DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
23582  duk_replace(ctx, 4);
23583  DUK_ASSERT_TOP(ctx, 5);
23584  }
23585  }
23586 
23587  if (!have_acc) {
23588  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
23589  }
23590 
23591  DUK_ASSERT_TOP(ctx, 5);
23592  return 1;
23593 }
23594 
23595 #endif /* DUK_USE_ARRAY_BUILTIN */
23596 
23597 /* automatic undefs */
23598 #undef DUK__ARRAY_MID_JOIN_LIMIT
23599 #undef DUK__ITER_EVERY
23600 #undef DUK__ITER_FILTER
23601 #undef DUK__ITER_FOREACH
23602 #undef DUK__ITER_MAP
23603 #undef DUK__ITER_SOME
23604 /*
23605  * Boolean built-ins
23606  */
23607 
23608 /* #include duk_internal.h -> already included */
23609 
23610 #if defined(DUK_USE_BOOLEAN_BUILTIN)
23611 
23612 /* Shared helper to provide toString() and valueOf(). Checks 'this', gets
23613  * the primitive value to stack top, and optionally coerces with ToString().
23614  */
23615 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx) {
23616  duk_tval *tv;
23617  duk_hobject *h;
23618  duk_small_int_t coerce_tostring = duk_get_current_magic(ctx);
23619 
23620  /* XXX: there is room to use a shared helper here, many built-ins
23621  * check the 'this' type, and if it's an object, check its class,
23622  * then get its internal value, etc.
23623  */
23624 
23625  duk_push_this(ctx);
23626  tv = duk_get_tval(ctx, -1);
23627  DUK_ASSERT(tv != NULL);
23628 
23629  if (DUK_TVAL_IS_BOOLEAN(tv)) {
23630  goto type_ok;
23631  } else if (DUK_TVAL_IS_OBJECT(tv)) {
23632  h = DUK_TVAL_GET_OBJECT(tv);
23633  DUK_ASSERT(h != NULL);
23634 
23635  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
23636  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
23637  DUK_ASSERT(duk_is_boolean(ctx, -1));
23638  goto type_ok;
23639  }
23640  }
23641 
23642  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
23643  /* never here */
23644 
23645  type_ok:
23646  if (coerce_tostring) {
23647  duk_to_string(ctx, -1);
23648  }
23649  return 1;
23650 }
23651 
23652 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx) {
23653  duk_hthread *thr = (duk_hthread *) ctx;
23654  duk_hobject *h_this;
23655 
23656  DUK_UNREF(thr);
23657 
23658  duk_to_boolean(ctx, 0);
23659 
23660  if (duk_is_constructor_call(ctx)) {
23661  /* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
23662  duk_push_this(ctx);
23663  h_this = duk_known_hobject(ctx, -1);
23664  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
23665 
23666  DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
23667 
23668  duk_dup_0(ctx); /* -> [ val obj val ] */
23669  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE); /* XXX: proper flags? */
23670  } /* unbalanced stack */
23671 
23672  return 1;
23673 }
23674 
23675 #endif /* DUK_USE_BOOLEAN_BUILTIN */
23676 /*
23677  * ES2015 TypedArray and Node.js Buffer built-ins
23678  */
23679 
23680 /* #include duk_internal.h -> already included */
23681 
23682 /*
23683  * Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
23684  */
23685 
23686 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
23687 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
23688  * default internal prototype.
23689  */
23690 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
23691  DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
23692  DUK_BIDX_DATAVIEW_PROTOTYPE,
23693  DUK_BIDX_INT8ARRAY_PROTOTYPE,
23694  DUK_BIDX_UINT8ARRAY_PROTOTYPE,
23695  DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
23696  DUK_BIDX_INT16ARRAY_PROTOTYPE,
23697  DUK_BIDX_UINT16ARRAY_PROTOTYPE,
23698  DUK_BIDX_INT32ARRAY_PROTOTYPE,
23699  DUK_BIDX_UINT32ARRAY_PROTOTYPE,
23700  DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
23701  DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
23702 };
23703 
23704 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
23705  * Sync with duk_hbufobj.h and duk_hobject.h.
23706  */
23707 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
23708  DUK_HOBJECT_CLASS_UINT8ARRAY,
23709  DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
23710  DUK_HOBJECT_CLASS_INT8ARRAY,
23711  DUK_HOBJECT_CLASS_UINT16ARRAY,
23712  DUK_HOBJECT_CLASS_INT16ARRAY,
23713  DUK_HOBJECT_CLASS_UINT32ARRAY,
23714  DUK_HOBJECT_CLASS_INT32ARRAY,
23715  DUK_HOBJECT_CLASS_FLOAT32ARRAY,
23716  DUK_HOBJECT_CLASS_FLOAT64ARRAY
23717 };
23718 
23719 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
23720  * Sync with duk_hbufobj.h.
23721  */
23722 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
23723  DUK_BIDX_UINT8ARRAY_PROTOTYPE,
23724  DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
23725  DUK_BIDX_INT8ARRAY_PROTOTYPE,
23726  DUK_BIDX_UINT16ARRAY_PROTOTYPE,
23727  DUK_BIDX_INT16ARRAY_PROTOTYPE,
23728  DUK_BIDX_UINT32ARRAY_PROTOTYPE,
23729  DUK_BIDX_INT32ARRAY_PROTOTYPE,
23730  DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
23731  DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
23732 };
23733 
23734 /* Map DUK__FLD_xxx to byte size. */
23735 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
23736  1, /* DUK__FLD_8BIT */
23737  2, /* DUK__FLD_16BIT */
23738  4, /* DUK__FLD_32BIT */
23739  4, /* DUK__FLD_FLOAT */
23740  8, /* DUK__FLD_DOUBLE */
23741  0 /* DUK__FLD_VARINT; not relevant here */
23742 };
23743 
23744 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
23745  * are compatible with a blind byte copy for the TypedArray set() method (also
23746  * used for TypedArray constructor). Array index is target buffer elem type,
23747  * bitfield indicates compatible source types. The types must have same byte
23748  * size and they must be coercion compatible.
23749  */
23750 #if !defined(DUK_USE_PREFER_SIZE)
23751 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
23752  /* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
23753  (1U << DUK_HBUFOBJ_ELEM_UINT8) |
23754  (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
23755  (1U << DUK_HBUFOBJ_ELEM_INT8),
23756 
23757  /* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
23758  * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
23759  */
23760  (1U << DUK_HBUFOBJ_ELEM_UINT8) |
23761  (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
23762 
23763  /* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
23764  (1U << DUK_HBUFOBJ_ELEM_UINT8) |
23765  (1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
23766  (1U << DUK_HBUFOBJ_ELEM_INT8),
23767 
23768  /* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
23769  (1U << DUK_HBUFOBJ_ELEM_UINT16) |
23770  (1U << DUK_HBUFOBJ_ELEM_INT16),
23771 
23772  /* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
23773  (1U << DUK_HBUFOBJ_ELEM_UINT16) |
23774  (1U << DUK_HBUFOBJ_ELEM_INT16),
23775 
23776  /* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
23777  (1U << DUK_HBUFOBJ_ELEM_UINT32) |
23778  (1U << DUK_HBUFOBJ_ELEM_INT32),
23779 
23780  /* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
23781  (1U << DUK_HBUFOBJ_ELEM_UINT32) |
23782  (1U << DUK_HBUFOBJ_ELEM_INT32),
23783 
23784  /* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
23785  (1U << DUK_HBUFOBJ_ELEM_FLOAT32),
23786 
23787  /* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
23788  (1U << DUK_HBUFOBJ_ELEM_FLOAT64)
23789 };
23790 #endif /* !DUK_USE_PREFER_SIZE */
23791 
23792 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_context *ctx) {
23793  duk_hthread *thr;
23794  duk_tval *tv_dst;
23795  duk_hbufobj *res;
23796 
23797  thr = (duk_hthread *) ctx;
23798  duk_push_this(ctx);
23799  DUK_ASSERT(duk_is_buffer(ctx, -1));
23800  res = (duk_hbufobj *) duk_to_hobject(ctx, -1);
23801  DUK_ASSERT_HBUFOBJ_VALID(res);
23802  DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(ctx, -1)));
23803 
23804  tv_dst = duk_get_borrowed_this_tval(ctx);
23805  DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
23806  duk_pop(ctx);
23807 
23808  return res;
23809 }
23810 
23811 #define DUK__BUFOBJ_FLAG_THROW (1 << 0)
23812 #define DUK__BUFOBJ_FLAG_PROMOTE (1 << 1)
23813 
23814 /* Shared helper. When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
23815  * always a duk_hbufobj *. Without the flag the return value can also be a
23816  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
23817  */
23818 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_context *ctx, duk_small_uint_t flags) {
23819  duk_hthread *thr;
23820  duk_tval *tv;
23821  duk_hbufobj *h_this;
23822 
23823  DUK_ASSERT(ctx != NULL);
23824  thr = (duk_hthread *) ctx;
23825 
23826  tv = duk_get_borrowed_this_tval(ctx);
23827  DUK_ASSERT(tv != NULL);
23828 
23829  if (DUK_TVAL_IS_OBJECT(tv)) {
23830  h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
23831  DUK_ASSERT(h_this != NULL);
23832  if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
23833  DUK_ASSERT_HBUFOBJ_VALID(h_this);
23834  return (duk_heaphdr *) h_this;
23835  }
23836  } else if (DUK_TVAL_IS_BUFFER(tv)) {
23837  if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
23838  /* Promote a plain buffer to a Uint8Array. This is very
23839  * inefficient but allows plain buffer to be used wherever an
23840  * Uint8Array is used with very small cost; hot path functions
23841  * like index read/write calls should provide direct buffer
23842  * support to avoid promotion.
23843  */
23844  /* XXX: make this conditional to a flag if call sites need it? */
23845  h_this = duk__hbufobj_promote_this(ctx);
23846  DUK_ASSERT(h_this != NULL);
23847  DUK_ASSERT_HBUFOBJ_VALID(h_this);
23848  return (duk_heaphdr *) h_this;
23849  } else {
23850  /* XXX: ugly, share return pointer for duk_hbuffer. */
23851  return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
23852  }
23853  }
23854 
23855  if (flags & DUK__BUFOBJ_FLAG_THROW) {
23856  DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
23857  }
23858  return NULL;
23859 }
23860 
23861 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
23862 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_context *ctx) {
23863  return (duk_hbufobj *) duk__getrequire_bufobj_this(ctx, DUK__BUFOBJ_FLAG_PROMOTE);
23864 }
23865 
23866 /* Check that 'this' is a duk_hbufobj and return a pointer to it
23867  * (NULL if not).
23868  */
23869 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_context *ctx) {
23870  return (duk_hbufobj *) duk__getrequire_bufobj_this(ctx, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
23871 }
23872 
23873 /* Check that value is a duk_hbufobj and return a pointer to it. */
23874 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_context *ctx, duk_idx_t idx) {
23875  duk_hthread *thr;
23876  duk_tval *tv;
23877  duk_hbufobj *h_obj;
23878 
23879  thr = (duk_hthread *) ctx;
23880 
23881  /* Don't accept relative indices now. */
23882  DUK_ASSERT(idx >= 0);
23883 
23884  tv = duk_require_tval(ctx, idx);
23885  DUK_ASSERT(tv != NULL);
23886  if (DUK_TVAL_IS_OBJECT(tv)) {
23887  h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
23888  DUK_ASSERT(h_obj != NULL);
23889  if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
23890  DUK_ASSERT_HBUFOBJ_VALID(h_obj);
23891  return h_obj;
23892  }
23893  } else if (DUK_TVAL_IS_BUFFER(tv)) {
23894  h_obj = (duk_hbufobj *) duk_to_hobject(ctx, idx);
23895  DUK_ASSERT(h_obj != NULL);
23896  DUK_ASSERT_HBUFOBJ_VALID(h_obj);
23897  return h_obj;
23898  }
23899 
23900  DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
23901  return NULL; /* not reachable */
23902 }
23903 
23904 DUK_LOCAL void duk__set_bufobj_buffer(duk_context *ctx, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
23905  duk_hthread *thr;
23906 
23907  thr = (duk_hthread *) ctx;
23908  DUK_UNREF(thr);
23909 
23910  DUK_ASSERT(ctx != NULL);
23911  DUK_ASSERT(h_bufobj != NULL);
23912  DUK_ASSERT(h_bufobj->buf == NULL); /* no need to decref */
23913  DUK_ASSERT(h_val != NULL);
23914  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
23915 
23916  h_bufobj->buf = h_val;
23917  DUK_HBUFFER_INCREF(thr, h_val);
23918  h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
23919  DUK_ASSERT(h_bufobj->shift == 0);
23920  DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
23921  DUK_ASSERT(h_bufobj->is_typedarray == 0);
23922 
23923  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
23924 }
23925 
23926 DUK_LOCAL duk_hbufobj *duk__push_arraybuffer_with_length(duk_context *ctx, duk_uint_t len) {
23927  duk_hbuffer *h_val;
23928  duk_hbufobj *h_bufobj;
23929 
23930  (void) duk_push_fixed_buffer_zero(ctx, (duk_size_t) len);
23931  h_val = (duk_hbuffer *) duk_known_hbuffer(ctx, -1);
23932 
23933  h_bufobj = duk_push_bufobj_raw(ctx,
23934  DUK_HOBJECT_FLAG_EXTENSIBLE |
23935  DUK_HOBJECT_FLAG_BUFOBJ |
23936  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
23937  DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
23938  DUK_ASSERT(h_bufobj != NULL);
23939 
23940  duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
23941  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
23942 
23943  return h_bufobj;
23944 }
23945 
23946 /* Shared offset/length coercion helper. */
23947 DUK_LOCAL void duk__resolve_offset_opt_length(duk_context *ctx,
23948  duk_hbufobj *h_bufarg,
23949  duk_idx_t idx_offset,
23950  duk_idx_t idx_length,
23951  duk_uint_t *out_offset,
23952  duk_uint_t *out_length,
23953  duk_bool_t throw_flag) {
23954  duk_hthread *thr;
23955  duk_int_t offset_signed;
23956  duk_int_t length_signed;
23957  duk_uint_t offset;
23958  duk_uint_t length;
23959 
23960  thr = (duk_hthread *) ctx;
23961  DUK_UNREF(thr);
23962 
23963  offset_signed = duk_to_int(ctx, idx_offset);
23964  if (offset_signed < 0) {
23965  goto fail_range;
23966  }
23967  offset = (duk_uint_t) offset_signed;
23968  if (offset > h_bufarg->length) {
23969  goto fail_range;
23970  }
23971  DUK_ASSERT_DISABLE(offset >= 0); /* unsigned */
23972  DUK_ASSERT(offset <= h_bufarg->length);
23973 
23974  if (duk_is_undefined(ctx, idx_length)) {
23975  DUK_ASSERT(h_bufarg->length >= offset);
23976  length = h_bufarg->length - offset; /* >= 0 */
23977  } else {
23978  length_signed = duk_to_int(ctx, idx_length);
23979  if (length_signed < 0) {
23980  goto fail_range;
23981  }
23982  length = (duk_uint_t) length_signed;
23983  DUK_ASSERT(h_bufarg->length >= offset);
23984  if (length > h_bufarg->length - offset) {
23985  /* Unlike for negative arguments, some call sites
23986  * want length to be clamped if it's positive.
23987  */
23988  if (throw_flag) {
23989  goto fail_range;
23990  } else {
23991  length = h_bufarg->length - offset;
23992  }
23993  }
23994  }
23995  DUK_ASSERT_DISABLE(length >= 0); /* unsigned */
23996  DUK_ASSERT(offset + length <= h_bufarg->length);
23997 
23998  *out_offset = offset;
23999  *out_length = length;
24000  return;
24001 
24002  fail_range:
24003  DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
24004 }
24005 
24006 /* Shared lenient buffer length clamping helper. No negative indices, no
24007  * element/byte shifting.
24008  */
24009 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_context *ctx,
24010  duk_int_t buffer_length,
24011  duk_idx_t idx_start,
24012  duk_idx_t idx_end,
24013  duk_int_t *out_start_offset,
24014  duk_int_t *out_end_offset) {
24015  duk_int_t start_offset;
24016  duk_int_t end_offset;
24017 
24018  DUK_ASSERT(out_start_offset != NULL);
24019  DUK_ASSERT(out_end_offset != NULL);
24020 
24021  /* undefined coerces to zero which is correct */
24022  start_offset = duk_to_int_clamped(ctx, idx_start, 0, buffer_length);
24023  if (duk_is_undefined(ctx, idx_end)) {
24024  end_offset = buffer_length;
24025  } else {
24026  end_offset = duk_to_int_clamped(ctx, idx_end, start_offset, buffer_length);
24027  }
24028 
24029  DUK_ASSERT(start_offset >= 0);
24030  DUK_ASSERT(start_offset <= buffer_length);
24031  DUK_ASSERT(end_offset >= 0);
24032  DUK_ASSERT(end_offset <= buffer_length);
24033  DUK_ASSERT(start_offset <= end_offset);
24034 
24035  *out_start_offset = start_offset;
24036  *out_end_offset = end_offset;
24037 }
24038 
24039 /* Shared lenient buffer length clamping helper. Indices are treated as
24040  * element indices (though output values are byte offsets) which only
24041  * really matters for TypedArray views as other buffer object have a zero
24042  * shift. Negative indices are counted from end of input slice; crossed
24043  * indices are clamped to zero length; and final indices are clamped
24044  * against input slice. Used for e.g. ArrayBuffer slice().
24045  */
24046 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_context *ctx,
24047  duk_int_t buffer_length,
24048  duk_uint8_t buffer_shift,
24049  duk_idx_t idx_start,
24050  duk_idx_t idx_end,
24051  duk_int_t *out_start_offset,
24052  duk_int_t *out_end_offset) {
24053  duk_int_t start_offset;
24054  duk_int_t end_offset;
24055 
24056  DUK_ASSERT(out_start_offset != NULL);
24057  DUK_ASSERT(out_end_offset != NULL);
24058 
24059  buffer_length >>= buffer_shift; /* as (full) elements */
24060 
24061  /* Resolve start/end offset as element indices first; arguments
24062  * at idx_start/idx_end are element offsets. Working with element
24063  * indices first also avoids potential for wrapping.
24064  */
24065 
24066  start_offset = duk_to_int(ctx, idx_start);
24067  if (start_offset < 0) {
24068  start_offset = buffer_length + start_offset;
24069  }
24070  if (duk_is_undefined(ctx, idx_end)) {
24071  end_offset = buffer_length;
24072  } else {
24073  end_offset = duk_to_int(ctx, idx_end);
24074  if (end_offset < 0) {
24075  end_offset = buffer_length + end_offset;
24076  }
24077  }
24078  /* Note: start_offset/end_offset can still be < 0 here. */
24079 
24080  if (start_offset < 0) {
24081  start_offset = 0;
24082  } else if (start_offset > buffer_length) {
24083  start_offset = buffer_length;
24084  }
24085  if (end_offset < start_offset) {
24086  end_offset = start_offset;
24087  } else if (end_offset > buffer_length) {
24088  end_offset = buffer_length;
24089  }
24090  DUK_ASSERT(start_offset >= 0);
24091  DUK_ASSERT(start_offset <= buffer_length);
24092  DUK_ASSERT(end_offset >= 0);
24093  DUK_ASSERT(end_offset <= buffer_length);
24094  DUK_ASSERT(start_offset <= end_offset);
24095 
24096  /* Convert indices to byte offsets. */
24097  start_offset <<= buffer_shift;
24098  end_offset <<= buffer_shift;
24099 
24100  *out_start_offset = start_offset;
24101  *out_end_offset = end_offset;
24102 }
24103 
24104 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_context *ctx, duk_idx_t idx) {
24105  if (duk_is_buffer(ctx, idx)) {
24106  duk_to_object(ctx, idx);
24107  }
24108 }
24109 
24110 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
24111  duk_context *ctx;
24112 
24113  ctx = (duk_context *) thr;
24114 
24115  /* Push Uint8Array which will share the same underlying buffer as
24116  * the plain buffer argument. Also create an ArrayBuffer with the
24117  * same backing for the result .buffer property.
24118  */
24119 
24120  duk_push_hbuffer(ctx, h_buf);
24121  duk_push_buffer_object(ctx, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
24122  duk_remove_m2(ctx);
24123 
24124 #if 0
24125  /* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
24126  h_bufobj = duk_push_bufobj_raw(ctx,
24127  DUK_HOBJECT_FLAG_EXTENSIBLE |
24128  DUK_HOBJECT_FLAG_BUFOBJ |
24129  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
24130  DUK_BIDX_UINT8ARRAY_PROTOTYPE);
24131  DUK_ASSERT(h_bufobj != NULL);
24132  duk__set_bufobj_buffer(ctx, h_bufobj, h_buf);
24133  h_bufobj->is_typedarray = 1;
24134  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
24135 
24136  h_arrbuf = duk_push_bufobj_raw(ctx,
24137  DUK_HOBJECT_FLAG_EXTENSIBLE |
24138  DUK_HOBJECT_FLAG_BUFOBJ |
24139  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
24140  DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
24141  DUK_ASSERT(h_arrbuf != NULL);
24142  duk__set_bufobj_buffer(ctx, h_arrbuf, h_buf);
24143  DUK_ASSERT(h_arrbuf->is_typedarray == 0);
24144  DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
24145 
24146  DUK_ASSERT(h_bufobj->buf_prop == NULL);
24147  h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
24148  DUK_ASSERT(h_arrbuf != NULL);
24149  DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
24150  duk_pop(ctx);
24151 #endif
24152 }
24153 
24154 /* Indexed read helper for buffer objects, also called from outside this file. */
24155 DUK_INTERNAL void duk_hbufobj_push_validated_read(duk_context *ctx, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
24156  duk_double_union du;
24157 
24158  DUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);
24159 
24160  switch (h_bufobj->elem_type) {
24161  case DUK_HBUFOBJ_ELEM_UINT8:
24162  case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
24163  duk_push_uint(ctx, (duk_uint_t) du.uc[0]);
24164  break;
24165  case DUK_HBUFOBJ_ELEM_INT8:
24166  duk_push_int(ctx, (duk_int_t) (duk_int8_t) du.uc[0]);
24167  break;
24168  case DUK_HBUFOBJ_ELEM_UINT16:
24169  duk_push_uint(ctx, (duk_uint_t) du.us[0]);
24170  break;
24171  case DUK_HBUFOBJ_ELEM_INT16:
24172  duk_push_int(ctx, (duk_int_t) (duk_int16_t) du.us[0]);
24173  break;
24174  case DUK_HBUFOBJ_ELEM_UINT32:
24175  duk_push_uint(ctx, (duk_uint_t) du.ui[0]);
24176  break;
24177  case DUK_HBUFOBJ_ELEM_INT32:
24178  duk_push_int(ctx, (duk_int_t) (duk_int32_t) du.ui[0]);
24179  break;
24180  case DUK_HBUFOBJ_ELEM_FLOAT32:
24181  duk_push_number(ctx, (duk_double_t) du.f[0]);
24182  break;
24183  case DUK_HBUFOBJ_ELEM_FLOAT64:
24184  duk_push_number(ctx, (duk_double_t) du.d);
24185  break;
24186  default:
24187  DUK_UNREACHABLE();
24188  }
24189 }
24190 
24191 /* Indexed write helper for buffer objects, also called from outside this file. */
24192 DUK_INTERNAL void duk_hbufobj_validated_write(duk_context *ctx, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
24193  duk_double_union du;
24194 
24195  /* NOTE! Caller must ensure that any side effects from the
24196  * coercions below are safe. If that cannot be guaranteed
24197  * (which is normally the case), caller must coerce the
24198  * argument using duk_to_number() before any pointer
24199  * validations; the result of duk_to_number() always coerces
24200  * without side effects here.
24201  */
24202 
24203  switch (h_bufobj->elem_type) {
24204  case DUK_HBUFOBJ_ELEM_UINT8:
24205  du.uc[0] = (duk_uint8_t) duk_to_uint32(ctx, -1);
24206  break;
24207  case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
24208  du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(ctx, -1);
24209  break;
24210  case DUK_HBUFOBJ_ELEM_INT8:
24211  du.uc[0] = (duk_uint8_t) duk_to_int32(ctx, -1);
24212  break;
24213  case DUK_HBUFOBJ_ELEM_UINT16:
24214  du.us[0] = (duk_uint16_t) duk_to_uint32(ctx, -1);
24215  break;
24216  case DUK_HBUFOBJ_ELEM_INT16:
24217  du.us[0] = (duk_uint16_t) duk_to_int32(ctx, -1);
24218  break;
24219  case DUK_HBUFOBJ_ELEM_UINT32:
24220  du.ui[0] = (duk_uint32_t) duk_to_uint32(ctx, -1);
24221  break;
24222  case DUK_HBUFOBJ_ELEM_INT32:
24223  du.ui[0] = (duk_uint32_t) duk_to_int32(ctx, -1);
24224  break;
24225  case DUK_HBUFOBJ_ELEM_FLOAT32:
24226  du.f[0] = (duk_float_t) duk_to_number_m1(ctx);
24227  break;
24228  case DUK_HBUFOBJ_ELEM_FLOAT64:
24229  du.d = (duk_double_t) duk_to_number_m1(ctx);
24230  break;
24231  default:
24232  DUK_UNREACHABLE();
24233  }
24234 
24235  DUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);
24236 }
24237 
24238 /* Helper to create a fixed buffer from argument value at index 0.
24239  * Node.js and allocPlain() compatible.
24240  */
24241 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_context *ctx) {
24242  duk_int_t len;
24243  duk_int_t i;
24244  duk_size_t buf_size;
24245  duk_uint8_t *buf;
24246 
24247  switch (duk_get_type(ctx, 0)) {
24248  case DUK_TYPE_NUMBER: {
24249  len = duk_to_int_clamped(ctx, 0, 0, DUK_INT_MAX);
24250  (void) duk_push_fixed_buffer_zero(ctx, (duk_size_t) len);
24251  break;
24252  }
24253  case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
24254  goto slow_copy;
24255  }
24256  case DUK_TYPE_OBJECT: {
24257  duk_hobject *h;
24258  duk_hbufobj *h_bufobj;
24259 
24260  /* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
24261  * that shares allocated memory with the given ArrayBuffer."
24262  * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
24263  */
24264 
24265  h = duk_known_hobject(ctx, 0);
24266  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
24267  DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
24268  h_bufobj = (duk_hbufobj *) h;
24269  if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
24270  DUK_ERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
24271  }
24272  if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
24273  /* No support for ArrayBuffers with slice
24274  * offset/length.
24275  */
24276  DUK_ERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
24277  }
24278  duk_push_hbuffer(ctx, h_bufobj->buf);
24279  return h_bufobj->buf;
24280  }
24281  goto slow_copy;
24282  }
24283  case DUK_TYPE_STRING: {
24284  /* ignore encoding for now */
24285  duk_require_hstring_notsymbol(ctx, 0);
24286  duk_dup_0(ctx);
24287  (void) duk_to_buffer(ctx, -1, &buf_size);
24288  break;
24289  }
24290  default:
24291  DUK_ERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
24292  }
24293 
24294  done:
24295  DUK_ASSERT(duk_is_buffer(ctx, -1));
24296  return duk_known_hbuffer(ctx, -1);
24297 
24298  slow_copy:
24299  /* XXX: fast path for typed arrays and other buffer objects? */
24300 
24301  (void) duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_LENGTH);
24302  len = duk_to_int_clamped(ctx, -1, 0, DUK_INT_MAX);
24303  duk_pop(ctx);
24304  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, (duk_size_t) len); /* no zeroing, all indices get initialized */
24305  for (i = 0; i < len; i++) {
24306  /* XXX: fast path for array or buffer arguments? */
24307  duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
24308  buf[i] = (duk_uint8_t) (duk_to_uint32(ctx, -1) & 0xffU);
24309  duk_pop(ctx);
24310  }
24311  goto done;
24312 }
24313 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24314 
24315 /*
24316  * Node.js Buffer constructor
24317  *
24318  * Node.js Buffers are just Uint8Arrays with internal prototype set to
24319  * Buffer.prototype so they're handled otherwise the same as Uint8Array.
24320  * However, the constructor arguments are very different so a separate
24321  * constructor entry point is used.
24322  */
24323 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24324 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx) {
24325  duk_hbuffer *h_buf;
24326 
24327  h_buf = duk__hbufobj_fixed_from_argvalue(ctx);
24328  DUK_ASSERT(h_buf != NULL);
24329 
24330  duk_push_buffer_object(ctx,
24331  -1,
24332  0,
24333  DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) h_buf),
24334  DUK_BUFOBJ_UINT8ARRAY);
24335  duk_push_hobject_bidx(ctx, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
24336  duk_set_prototype(ctx, -2);
24337 
24338  /* XXX: a more direct implementation */
24339 
24340  return 1;
24341 }
24342 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24343 
24344 /*
24345  * ArrayBuffer, DataView, and TypedArray constructors
24346  */
24347 
24348 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24349 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx) {
24350  duk_hthread *thr;
24351  duk_hbufobj *h_bufobj;
24352  duk_hbuffer *h_val;
24353  duk_int_t len;
24354 
24355  DUK_ASSERT_CTX_VALID(ctx);
24356  thr = (duk_hthread *) ctx;
24357  DUK_UNREF(thr);
24358 
24359  duk_require_constructor_call(ctx);
24360 
24361  len = duk_to_int(ctx, 0);
24362  if (len < 0) {
24363  goto fail_length;
24364  }
24365  (void) duk_push_fixed_buffer_zero(ctx, (duk_size_t) len);
24366  h_val = (duk_hbuffer *) duk_known_hbuffer(ctx, -1);
24367 
24368  h_bufobj = duk_push_bufobj_raw(ctx,
24369  DUK_HOBJECT_FLAG_EXTENSIBLE |
24370  DUK_HOBJECT_FLAG_BUFOBJ |
24371  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
24372  DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
24373  DUK_ASSERT(h_bufobj != NULL);
24374 
24375  duk__set_bufobj_buffer(ctx, h_bufobj, h_val);
24376  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
24377 
24378  return 1;
24379 
24380  fail_length:
24381  DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
24382 }
24383 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24384 
24385 
24386 /* Format of magic, bits:
24387  * 0...1: elem size shift (0-3)
24388  * 2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
24389  *
24390  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
24391  */
24392 
24393 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24394 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
24395  duk_hthread *thr;
24396  duk_tval *tv;
24397  duk_hobject *h_obj;
24398  duk_hbufobj *h_bufobj = NULL;
24399  duk_hbufobj *h_bufarr = NULL;
24400  duk_hbufobj *h_bufarg = NULL;
24401  duk_hbuffer *h_val;
24402  duk_small_uint_t magic;
24403  duk_small_uint_t shift;
24404  duk_small_uint_t elem_type;
24405  duk_small_uint_t elem_size;
24406  duk_small_uint_t class_num;
24407  duk_small_uint_t proto_bidx;
24408  duk_uint_t align_mask;
24409  duk_uint_t elem_length;
24410  duk_int_t elem_length_signed;
24411  duk_uint_t byte_length;
24412  duk_small_uint_t copy_mode;
24413 
24414  thr = (duk_hthread *) ctx;
24415  DUK_UNREF(thr);
24416 
24417  /* XXX: The same copy helpers could be shared with at least some
24418  * buffer functions.
24419  */
24420 
24421  duk_require_constructor_call(ctx);
24422 
24423  /* We could fit built-in index into magic but that'd make the magic
24424  * number dependent on built-in numbering (genbuiltins.py doesn't
24425  * handle that yet). So map both class and prototype from the
24426  * element type.
24427  */
24428  magic = duk_get_current_magic(ctx);
24429  shift = magic & 0x03; /* bits 0...1: shift */
24430  elem_type = (magic >> 2) & 0x0f; /* bits 2...5: type */
24431  elem_size = 1 << shift;
24432  align_mask = elem_size - 1;
24433  DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
24434  proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
24435  DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
24436  DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
24437  class_num = duk__buffer_class_from_elemtype[elem_type];
24438 
24439  DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
24440  "elem_size=%d, proto_bidx=%d, class_num=%d",
24441  (int) magic, (int) shift, (int) elem_type, (int) elem_size,
24442  (int) proto_bidx, (int) class_num));
24443 
24444  /* Argument variants. When the argument is an ArrayBuffer a view to
24445  * the same buffer is created; otherwise a new ArrayBuffer is always
24446  * created.
24447  */
24448 
24449  /* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
24450  * coerce to an ArrayBuffer object and use that as .buffer. The underlying
24451  * buffer will be the same but result .buffer !== inputPlainBuffer.
24452  */
24453  duk_hbufobj_promote_plain(ctx, 0);
24454 
24455  tv = duk_get_tval(ctx, 0);
24456  DUK_ASSERT(tv != NULL); /* arg count */
24457  if (DUK_TVAL_IS_OBJECT(tv)) {
24458  h_obj = DUK_TVAL_GET_OBJECT(tv);
24459  DUK_ASSERT(h_obj != NULL);
24460 
24461  if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
24462  /* ArrayBuffer: unlike any other argument variant, create
24463  * a view into the existing buffer.
24464  */
24465 
24466  duk_int_t byte_offset_signed;
24467  duk_uint_t byte_offset;
24468 
24469  h_bufarg = (duk_hbufobj *) h_obj;
24470 
24471  byte_offset_signed = duk_to_int(ctx, 1);
24472  if (byte_offset_signed < 0) {
24473  goto fail_arguments;
24474  }
24475  byte_offset = (duk_uint_t) byte_offset_signed;
24476  if (byte_offset > h_bufarg->length ||
24477  (byte_offset & align_mask) != 0) {
24478  /* Must be >= 0 and multiple of element size. */
24479  goto fail_arguments;
24480  }
24481  if (duk_is_undefined(ctx, 2)) {
24482  DUK_ASSERT(h_bufarg->length >= byte_offset);
24483  byte_length = h_bufarg->length - byte_offset;
24484  if ((byte_length & align_mask) != 0) {
24485  /* Must be element size multiple from
24486  * start offset to end of buffer.
24487  */
24488  goto fail_arguments;
24489  }
24490  elem_length = (byte_length >> shift);
24491  } else {
24492  elem_length_signed = duk_to_int(ctx, 2);
24493  if (elem_length_signed < 0) {
24494  goto fail_arguments;
24495  }
24496  elem_length = (duk_uint_t) elem_length_signed;
24497  byte_length = elem_length << shift;
24498  if ((byte_length >> shift) != elem_length) {
24499  /* Byte length would overflow. */
24500  /* XXX: easier check with less code? */
24501  goto fail_arguments;
24502  }
24503  DUK_ASSERT(h_bufarg->length >= byte_offset);
24504  if (byte_length > h_bufarg->length - byte_offset) {
24505  /* Not enough data. */
24506  goto fail_arguments;
24507  }
24508  }
24509  DUK_UNREF(elem_length);
24510  DUK_ASSERT_DISABLE(byte_offset >= 0);
24511  DUK_ASSERT(byte_offset <= h_bufarg->length);
24512  DUK_ASSERT_DISABLE(byte_length >= 0);
24513  DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
24514  DUK_ASSERT((elem_length << shift) == byte_length);
24515 
24516  h_bufobj = duk_push_bufobj_raw(ctx,
24517  DUK_HOBJECT_FLAG_EXTENSIBLE |
24518  DUK_HOBJECT_FLAG_BUFOBJ |
24519  DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
24520  proto_bidx);
24521  h_val = h_bufarg->buf;
24522  if (h_val == NULL) {
24523  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
24524  }
24525  h_bufobj->buf = h_val;
24526  DUK_HBUFFER_INCREF(thr, h_val);
24527  h_bufobj->offset = h_bufarg->offset + byte_offset;
24528  h_bufobj->length = byte_length;
24529  h_bufobj->shift = (duk_uint8_t) shift;
24530  h_bufobj->elem_type = (duk_uint8_t) elem_type;
24531  h_bufobj->is_typedarray = 1;
24532  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
24533 
24534  /* Set .buffer to the argument ArrayBuffer. */
24535  DUK_ASSERT(h_bufobj->buf_prop == NULL);
24536  h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
24537  DUK_ASSERT(h_bufarg != NULL);
24538  DUK_HBUFOBJ_INCREF(thr, h_bufarg);
24539  return 1;
24540  } else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
24541  /* TypedArray (or other non-ArrayBuffer duk_hbufobj).
24542  * Conceptually same behavior as for an Array-like argument,
24543  * with a few fast paths.
24544  */
24545 
24546  h_bufarg = (duk_hbufobj *) h_obj;
24547  DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
24548  elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
24549  if (h_bufarg->buf == NULL) {
24550  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
24551  }
24552 
24553  /* Select copy mode. Must take into account element
24554  * compatibility and validity of the underlying source
24555  * buffer.
24556  */
24557 
24558  DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
24559  "src byte_length=%ld, src shift=%d, "
24560  "src/dst elem_length=%ld; "
24561  "dst shift=%d -> dst byte_length=%ld",
24562  (long) h_bufarg->length, (int) h_bufarg->shift,
24563  (long) elem_length_signed, (int) shift,
24564  (long) (elem_length_signed << shift)));
24565 
24566  copy_mode = 2; /* default is explicit index read/write copy */
24567 #if !defined(DUK_USE_PREFER_SIZE)
24568  /* With a size optimized build copy_mode 2 is enough.
24569  * Modes 0 and 1 are faster but conceptually the same.
24570  */
24571  DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
24572  if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
24573  if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
24574  DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
24575  DUK_ASSERT(shift == h_bufarg->shift); /* byte sizes will match */
24576  copy_mode = 0;
24577  } else {
24578  DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
24579  copy_mode = 1;
24580  }
24581  }
24582 #endif /* !DUK_USE_PREFER_SIZE */
24583  } else {
24584  /* Array or Array-like */
24585  elem_length_signed = (duk_int_t) duk_get_length(ctx, 0);
24586  copy_mode = 2;
24587  }
24588  } else {
24589  /* Non-object argument is simply int coerced, matches
24590  * V8 behavior (except for "null", which we coerce to
24591  * 0 but V8 TypeErrors).
24592  */
24593  elem_length_signed = duk_to_int(ctx, 0);
24594  copy_mode = 3;
24595  }
24596  if (elem_length_signed < 0) {
24597  goto fail_arguments;
24598  }
24599  elem_length = (duk_uint_t) elem_length_signed;
24600  byte_length = (duk_uint_t) (elem_length << shift);
24601  if ((byte_length >> shift) != elem_length) {
24602  /* Byte length would overflow. */
24603  /* XXX: easier check with less code? */
24604  goto fail_arguments;
24605  }
24606 
24607  DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
24608  (long) elem_length, (long) byte_length));
24609 
24610  /* ArrayBuffer argument is handled specially above; the rest of the
24611  * argument variants are handled by shared code below.
24612  */
24613 
24614  /* Push a new ArrayBuffer (becomes view .buffer) */
24615  h_bufarr = duk__push_arraybuffer_with_length(ctx, byte_length);
24616  DUK_ASSERT(h_bufarr != NULL);
24617  h_val = h_bufarr->buf;
24618  DUK_ASSERT(h_val != NULL);
24619 
24620  /* Push the resulting view object and attach the ArrayBuffer. */
24621  h_bufobj = duk_push_bufobj_raw(ctx,
24622  DUK_HOBJECT_FLAG_EXTENSIBLE |
24623  DUK_HOBJECT_FLAG_BUFOBJ |
24624  DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
24625  proto_bidx);
24626 
24627  h_bufobj->buf = h_val;
24628  DUK_HBUFFER_INCREF(thr, h_val);
24629  DUK_ASSERT(h_bufobj->offset == 0);
24630  h_bufobj->length = byte_length;
24631  h_bufobj->shift = (duk_uint8_t) shift;
24632  h_bufobj->elem_type = (duk_uint8_t) elem_type;
24633  h_bufobj->is_typedarray = 1;
24634  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
24635 
24636  /* Set .buffer */
24637  DUK_ASSERT(h_bufobj->buf_prop == NULL);
24638  h_bufobj->buf_prop = (duk_hobject *) h_bufarr;
24639  DUK_ASSERT(h_bufarr != NULL);
24640  DUK_HBUFOBJ_INCREF(thr, h_bufarr);
24641 
24642  /* Copy values, the copy method depends on the arguments.
24643  *
24644  * Copy mode decision may depend on the validity of the underlying
24645  * buffer of the source argument; there must be no harmful side effects
24646  * from there to here for copy_mode to still be valid.
24647  */
24648  DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
24649  switch (copy_mode) {
24650  /* Copy modes 0 and 1 can be omitted in size optimized build,
24651  * copy mode 2 handles them (but more slowly).
24652  */
24653 #if !defined(DUK_USE_PREFER_SIZE)
24654  case 0: {
24655  /* Use byte copy. */
24656 
24657  duk_uint8_t *p_src;
24658  duk_uint8_t *p_dst;
24659 
24660  DUK_ASSERT(h_bufobj != NULL);
24661  DUK_ASSERT(h_bufobj->buf != NULL);
24662  DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
24663  DUK_ASSERT(h_bufarg != NULL);
24664  DUK_ASSERT(h_bufarg->buf != NULL);
24665  DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
24666 
24667  p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
24668  p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
24669 
24670  DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
24671  (void *) p_src, (void *) p_dst, (long) byte_length));
24672 
24673  DUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);
24674  break;
24675  }
24676  case 1: {
24677  /* Copy values through direct validated reads and writes. */
24678 
24679  duk_small_uint_t src_elem_size;
24680  duk_small_uint_t dst_elem_size;
24681  duk_uint8_t *p_src;
24682  duk_uint8_t *p_src_end;
24683  duk_uint8_t *p_dst;
24684 
24685  DUK_ASSERT(h_bufobj != NULL);
24686  DUK_ASSERT(h_bufobj->buf != NULL);
24687  DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
24688  DUK_ASSERT(h_bufarg != NULL);
24689  DUK_ASSERT(h_bufarg->buf != NULL);
24690  DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
24691 
24692  src_elem_size = 1 << h_bufarg->shift;
24693  dst_elem_size = elem_size;
24694 
24695  p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
24696  p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
24697  p_src_end = p_src + h_bufarg->length;
24698 
24699  DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
24700  "src_elem_size=%d, dst_elem_size=%d",
24701  (void *) p_src, (void *) p_src_end, (void *) p_dst,
24702  (int) src_elem_size, (int) dst_elem_size));
24703 
24704  while (p_src != p_src_end) {
24705  DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
24706  "p_src=%p, p_src_end=%p, p_dst=%p",
24707  (void *) p_src, (void *) p_src_end, (void *) p_dst));
24708  /* A validated read() is always a number, so it's write coercion
24709  * is always side effect free an won't invalidate pointers etc.
24710  */
24711  duk_hbufobj_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
24712  duk_hbufobj_validated_write(ctx, h_bufobj, p_dst, dst_elem_size);
24713  duk_pop(ctx);
24714  p_src += src_elem_size;
24715  p_dst += dst_elem_size;
24716  }
24717  break;
24718  }
24719 #endif /* !DUK_USE_PREFER_SIZE */
24720  case 2: {
24721  /* Copy values by index reads and writes. Let virtual
24722  * property handling take care of coercion.
24723  */
24724  duk_uint_t i;
24725 
24726  DUK_DDD(DUK_DDDPRINT("using slow copy"));
24727 
24728  for (i = 0; i < elem_length; i++) {
24729  duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
24730  duk_put_prop_index(ctx, -2, (duk_uarridx_t) i);
24731  }
24732  break;
24733  }
24734  default:
24735  case 3: {
24736  /* No copy, leave zero bytes in the buffer. There's no
24737  * ambiguity with Float32/Float64 because zero bytes also
24738  * represent 0.0.
24739  */
24740 
24741  DUK_DDD(DUK_DDDPRINT("using no copy"));
24742  break;
24743  }
24744  }
24745 
24746  return 1;
24747 
24748  fail_arguments:
24749  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
24750 }
24751 #else /* DUK_USE_BUFFEROBJECT_SUPPORT */
24752 /* When bufferobject support is disabled, new Uint8Array() could still be
24753  * supported to create a plain fixed buffer. Disabled for now.
24754  */
24755 #if 0
24756 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx) {
24757  duk_int_t elem_length_signed;
24758  duk_uint_t byte_length;
24759 
24760  /* XXX: The same copy helpers could be shared with at least some
24761  * buffer functions.
24762  */
24763 
24764  duk_require_constructor_call(ctx);
24765 
24766  elem_length_signed = duk_require_int(ctx, 0);
24767  if (elem_length_signed < 0) {
24768  goto fail_arguments;
24769  }
24770  byte_length = (duk_uint_t) elem_length_signed;
24771 
24772  (void) duk_push_fixed_buffer_zero(ctx, (duk_size_t) byte_length);
24773  return 1;
24774 
24775  fail_arguments:
24776  DUK_DCERROR_RANGE_INVALID_ARGS((duk_hthread *) ctx);
24777 }
24778 #endif /* 0 */
24779 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24780 
24781 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24782 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx) {
24783  duk_hbufobj *h_bufarg;
24784  duk_hbufobj *h_bufobj;
24785  duk_hbuffer *h_val;
24786  duk_uint_t offset;
24787  duk_uint_t length;
24788 
24789  duk_require_constructor_call(ctx);
24790 
24791  h_bufarg = duk__require_bufobj_value(ctx, 0);
24792  DUK_ASSERT(h_bufarg != NULL);
24793  if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
24794  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
24795  }
24796 
24797  duk__resolve_offset_opt_length(ctx, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
24798  DUK_ASSERT(offset <= h_bufarg->length);
24799  DUK_ASSERT(offset + length <= h_bufarg->length);
24800 
24801  h_bufobj = duk_push_bufobj_raw(ctx,
24802  DUK_HOBJECT_FLAG_EXTENSIBLE |
24803  DUK_HOBJECT_FLAG_BUFOBJ |
24804  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
24805  DUK_BIDX_DATAVIEW_PROTOTYPE);
24806 
24807  h_val = h_bufarg->buf;
24808  if (h_val == NULL) {
24809  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
24810  }
24811  h_bufobj->buf = h_val;
24812  DUK_HBUFFER_INCREF(thr, h_val);
24813  h_bufobj->offset = h_bufarg->offset + offset;
24814  h_bufobj->length = length;
24815  DUK_ASSERT(h_bufobj->shift == 0);
24816  DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
24817  DUK_ASSERT(h_bufobj->is_typedarray == 0);
24818 
24819  DUK_ASSERT(h_bufobj->buf_prop == NULL);
24820  h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
24821  DUK_ASSERT(h_bufarg != NULL);
24822  DUK_HBUFOBJ_INCREF((duk_hthread *) ctx, h_bufarg);
24823 
24824  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
24825  return 1;
24826 }
24827 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24828 
24829 /*
24830  * ArrayBuffer.isView()
24831  */
24832 
24833 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24834 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx) {
24835  duk_hobject *h_obj;
24836  duk_bool_t ret = 0;
24837 
24838  if (duk_is_buffer(ctx, 0)) {
24839  ret = 1;
24840  } else {
24841  h_obj = duk_get_hobject(ctx, 0);
24842  if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
24843  /* DataView needs special casing: ArrayBuffer.isView() is
24844  * true, but ->is_typedarray is 0.
24845  */
24846  ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
24847  (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
24848  }
24849  }
24850  duk_push_boolean(ctx, ret);
24851  return 1;
24852 }
24853 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24854 
24855 /*
24856  * Uint8Array.allocPlain()
24857  */
24858 
24859 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24860 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx) {
24861  duk__hbufobj_fixed_from_argvalue(ctx);
24862  return 1;
24863 }
24864 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24865 
24866 /*
24867  * Uint8Array.plainOf()
24868  */
24869 
24870 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24871 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx) {
24872  duk_hbufobj *h_bufobj;
24873 
24874 #if !defined(DUK_USE_PREFER_SIZE)
24875  /* Avoid churn if argument is already a plain buffer. */
24876  if (duk_is_buffer(ctx, 0)) {
24877  return 1;
24878  }
24879 #endif
24880 
24881  /* Promotes plain buffers to ArrayBuffers, so for a plain buffer
24882  * argument we'll create a pointless temporary (but still work
24883  * correctly).
24884  */
24885  h_bufobj = duk__require_bufobj_value(ctx, 0);
24886  if (h_bufobj->buf == NULL) {
24887  duk_push_undefined(ctx);
24888  } else {
24889  duk_push_hbuffer(ctx, h_bufobj->buf);
24890  }
24891  return 1;
24892 }
24893 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24894 
24895 /*
24896  * Node.js Buffer: toString([encoding], [start], [end])
24897  */
24898 
24899 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24900 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx) {
24901  duk_hthread *thr;
24902  duk_hbufobj *h_this;
24903  duk_int_t start_offset, end_offset;
24904  duk_uint8_t *buf_slice;
24905  duk_size_t slice_length;
24906 
24907  thr = (duk_hthread *) ctx;
24908  DUK_UNREF(thr);
24909 
24910  h_this = duk__get_bufobj_this(ctx);
24911  if (h_this == NULL) {
24912  /* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
24913  duk_push_string(ctx, "[object Object]");
24914  return 1;
24915  }
24916  DUK_ASSERT_HBUFOBJ_VALID(h_this);
24917 
24918  /* Ignore encoding for now. */
24919 
24920  duk__clamp_startend_nonegidx_noshift(ctx,
24921  (duk_int_t) h_this->length,
24922  1 /*idx_start*/,
24923  2 /*idx_end*/,
24924  &start_offset,
24925  &end_offset);
24926 
24927  slice_length = (duk_size_t) (end_offset - start_offset);
24928  buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, slice_length); /* all bytes initialized below */
24929  DUK_ASSERT(buf_slice != NULL);
24930 
24931  /* Neutered or uncovered, TypeError. */
24932  if (h_this->buf == NULL ||
24933  !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length)) {
24934  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
24935  }
24936 
24937  /* XXX: ideally we wouldn't make a copy but a view into the buffer for the
24938  * decoding process. Or the decoding helper could be changed to accept
24939  * the slice info (a buffer pointer is NOT a good approach because guaranteeing
24940  * its stability is difficult).
24941  */
24942 
24943  DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, start_offset + slice_length));
24944  DUK_MEMCPY((void *) buf_slice,
24945  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
24946  (size_t) slice_length);
24947 
24948  /* Use the equivalent of: new TextEncoder().encode(this) to convert the
24949  * string. Result will be valid UTF-8; non-CESU-8 inputs are currently
24950  * interpreted loosely. Value stack convention is a bit odd for now.
24951  */
24952  duk_replace(ctx, 0);
24953  duk_set_top(ctx, 1);
24954  return duk_textdecoder_decode_utf8_nodejs(ctx);
24955 }
24956 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
24957 
24958 /*
24959  * Node.js Buffer.prototype: toJSON()
24960  */
24961 
24962 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
24963 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx) {
24964  duk_hthread *thr;
24965  duk_hbufobj *h_this;
24966  duk_harray *h_arr;
24967  duk_uint8_t *buf;
24968  duk_uint_t i, n;
24969  duk_tval *tv;
24970 
24971  thr = (duk_hthread *) ctx;
24972  DUK_UNREF(thr);
24973 
24974  h_this = duk__require_bufobj_this(ctx);
24975  DUK_ASSERT(h_this != NULL);
24976 
24977  if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
24978  /* Serialize uncovered backing buffer as a null; doesn't
24979  * really matter as long we're memory safe.
24980  */
24981  duk_push_null(ctx);
24982  return 1;
24983  }
24984 
24985  duk_push_object(ctx);
24986  duk_push_hstring_stridx(ctx, DUK_STRIDX_UC_BUFFER);
24987  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_TYPE);
24988 
24989  DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
24990  h_arr = duk_push_harray_with_size(ctx, (duk_uint32_t) h_this->length); /* XXX: needs revision with >4G buffers */
24991  DUK_ASSERT(h_arr != NULL);
24992  DUK_ASSERT(h_arr->length == h_this->length);
24993  tv = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
24994 
24995  DUK_ASSERT(h_this->buf != NULL);
24996  buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
24997  for (i = 0, n = h_this->length; i < n; i++) {
24998  DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]); /* no need for decref or incref */
24999  }
25000  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_DATA);
25001 
25002  return 1;
25003 }
25004 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25005 
25006 /*
25007  * Node.js Buffer.prototype.equals()
25008  * Node.js Buffer.prototype.compare()
25009  * Node.js Buffer.compare()
25010  */
25011 
25012 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25013 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx) {
25014  duk_hthread *thr;
25015  duk_small_uint_t magic;
25016  duk_hbufobj *h_bufarg1;
25017  duk_hbufobj *h_bufarg2;
25018  duk_small_int_t comp_res;
25019 
25020  thr = (duk_hthread *) ctx;
25021  DUK_UNREF(thr);
25022 
25023  /* XXX: keep support for plain buffers and non-Node.js buffers? */
25024 
25025  magic = duk_get_current_magic(ctx);
25026  if (magic & 0x02) {
25027  /* Static call style. */
25028  h_bufarg1 = duk__require_bufobj_value(ctx, 0);
25029  h_bufarg2 = duk__require_bufobj_value(ctx, 1);
25030  } else {
25031  h_bufarg1 = duk__require_bufobj_this(ctx);
25032  h_bufarg2 = duk__require_bufobj_value(ctx, 0);
25033  }
25034  DUK_ASSERT(h_bufarg1 != NULL);
25035  DUK_ASSERT(h_bufarg2 != NULL);
25036 
25037  /* We want to compare the slice/view areas of the arguments.
25038  * If either slice/view is invalid (underlying buffer is shorter)
25039  * ensure equals() is false, but otherwise the only thing that
25040  * matters is to be memory safe.
25041  */
25042 
25043  if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
25044  DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
25045  comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
25046  (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
25047  (duk_size_t) h_bufarg1->length,
25048  (duk_size_t) h_bufarg2->length);
25049  } else {
25050  comp_res = -1; /* either nonzero value is ok */
25051  }
25052 
25053  if (magic & 0x01) {
25054  /* compare: similar to string comparison but for buffer data. */
25055  duk_push_int(ctx, comp_res);
25056  } else {
25057  /* equals */
25058  duk_push_boolean(ctx, (comp_res == 0));
25059  }
25060 
25061  return 1;
25062 }
25063 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25064 
25065 /*
25066  * Node.js Buffer.prototype.fill()
25067  */
25068 
25069 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25070 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx) {
25071  duk_hthread *thr;
25072  duk_hbufobj *h_this;
25073  const duk_uint8_t *fill_str_ptr;
25074  duk_size_t fill_str_len;
25075  duk_uint8_t fill_value;
25076  duk_int_t fill_offset;
25077  duk_int_t fill_end;
25078  duk_size_t fill_length;
25079  duk_uint8_t *p;
25080 
25081  thr = (duk_hthread *) ctx;
25082  DUK_UNREF(thr);
25083 
25084  h_this = duk__require_bufobj_this(ctx);
25085  DUK_ASSERT(h_this != NULL);
25086  if (h_this->buf == NULL) {
25087  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
25088  }
25089 
25090  /* [ value offset end ] */
25091 
25092  if (duk_is_string_notsymbol(ctx, 0)) {
25093  fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(ctx, 0, &fill_str_len);
25094  DUK_ASSERT(fill_str_ptr != NULL);
25095  } else {
25096  /* Symbols get ToNumber() coerced and cause TypeError. */
25097  fill_value = (duk_uint8_t) duk_to_uint32(ctx, 0);
25098  fill_str_ptr = (const duk_uint8_t *) &fill_value;
25099  fill_str_len = 1;
25100  }
25101 
25102  /* Fill offset handling is more lenient than in Node.js. */
25103 
25104  duk__clamp_startend_nonegidx_noshift(ctx,
25105  (duk_int_t) h_this->length,
25106  1 /*idx_start*/,
25107  2 /*idx_end*/,
25108  &fill_offset,
25109  &fill_end);
25110 
25111  DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
25112  (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
25113 
25114  DUK_ASSERT(fill_end - fill_offset >= 0);
25115  DUK_ASSERT(h_this->buf != NULL);
25116 
25117  p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
25118  fill_length = (duk_size_t) (fill_end - fill_offset);
25119  if (fill_str_len == 1) {
25120  /* Handle single character fills as memset() even when
25121  * the fill data comes from a one-char argument.
25122  */
25123  DUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
25124  } else if (fill_str_len > 1) {
25125  duk_size_t i, n, t;
25126 
25127  for (i = 0, n = (fill_end - fill_offset), t = 0; i < n; i++) {
25128  p[i] = fill_str_ptr[t++];
25129  if (t >= fill_str_len) {
25130  t = 0;
25131  }
25132  }
25133  } else {
25134  DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
25135  }
25136 
25137  /* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
25138  duk_push_this(ctx);
25139  return 1;
25140 }
25141 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25142 
25143 /*
25144  * Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
25145  */
25146 
25147 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25148 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx) {
25149  duk_hthread *thr;
25150  duk_hbufobj *h_this;
25151  duk_uint_t offset;
25152  duk_uint_t length;
25153  const duk_uint8_t *str_data;
25154  duk_size_t str_len;
25155 
25156  thr = (duk_hthread *) ctx;
25157  DUK_UNREF(thr);
25158 
25159  /* XXX: very inefficient support for plain buffers */
25160  h_this = duk__require_bufobj_this(ctx);
25161  DUK_ASSERT(h_this != NULL);
25162 
25163  /* Argument must be a string, e.g. a buffer is not allowed. */
25164  str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(ctx, 0, &str_len);
25165 
25166  duk__resolve_offset_opt_length(ctx, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
25167  DUK_ASSERT(offset <= h_this->length);
25168  DUK_ASSERT(offset + length <= h_this->length);
25169 
25170  /* XXX: encoding is ignored now. */
25171 
25172  if (length > str_len) {
25173  length = (duk_uint_t) str_len;
25174  }
25175 
25176  if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
25177  /* Cannot overlap. */
25178  DUK_MEMCPY((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
25179  (const void *) str_data,
25180  (size_t) length);
25181  } else {
25182  DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
25183  }
25184 
25185  duk_push_uint(ctx, length);
25186  return 1;
25187 }
25188 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25189 
25190 /*
25191  * Node.js Buffer.prototype.copy()
25192  */
25193 
25194 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25195 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx) {
25196  duk_hthread *thr;
25197  duk_hbufobj *h_this;
25198  duk_hbufobj *h_bufarg;
25199  duk_int_t source_length;
25200  duk_int_t target_length;
25201  duk_int_t target_start, source_start, source_end;
25202  duk_uint_t target_ustart, source_ustart, source_uend;
25203  duk_uint_t copy_size = 0;
25204 
25205  /* [ targetBuffer targetStart sourceStart sourceEnd ] */
25206 
25207  thr = (duk_hthread *) ctx;
25208  DUK_UNREF(thr);
25209 
25210  h_this = duk__require_bufobj_this(ctx);
25211  h_bufarg = duk__require_bufobj_value(ctx, 0);
25212  DUK_ASSERT(h_this != NULL);
25213  DUK_ASSERT(h_bufarg != NULL);
25214  source_length = (duk_int_t) h_this->length;
25215  target_length = (duk_int_t) h_bufarg->length;
25216 
25217  target_start = duk_to_int(ctx, 1);
25218  source_start = duk_to_int(ctx, 2);
25219  if (duk_is_undefined(ctx, 3)) {
25220  source_end = source_length;
25221  } else {
25222  source_end = duk_to_int(ctx, 3);
25223  }
25224 
25225  DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
25226  "source_start=%ld, source_end=%ld, source_length=%ld",
25227  (long) target_start, (long) h_bufarg->length,
25228  (long) source_start, (long) source_end, (long) source_length));
25229 
25230  /* This behavior mostly mimics Node.js now. */
25231 
25232  if (source_start < 0 || source_end < 0 || target_start < 0) {
25233  /* Negative offsets cause a RangeError. */
25234  goto fail_bounds;
25235  }
25236  source_ustart = (duk_uint_t) source_start;
25237  source_uend = (duk_uint_t) source_end;
25238  target_ustart = (duk_uint_t) target_start;
25239  if (source_ustart >= source_uend || /* crossed offsets or zero size */
25240  source_ustart >= (duk_uint_t) source_length || /* source out-of-bounds (but positive) */
25241  target_ustart >= (duk_uint_t) target_length) { /* target out-of-bounds (but positive) */
25242  goto silent_ignore;
25243  }
25244  if (source_uend >= (duk_uint_t) source_length) {
25245  /* Source end clamped silently to available length. */
25246  source_uend = source_length;
25247  }
25248  copy_size = source_uend - source_ustart;
25249  if (target_ustart + copy_size > (duk_uint_t) target_length) {
25250  /* Clamp to target's end if too long.
25251  *
25252  * NOTE: there's no overflow possibility in the comparison;
25253  * both target_ustart and copy_size are >= 0 and based on
25254  * values in duk_int_t range. Adding them as duk_uint_t
25255  * values is then guaranteed not to overflow.
25256  */
25257  DUK_ASSERT(target_ustart + copy_size >= target_ustart); /* no overflow */
25258  DUK_ASSERT(target_ustart + copy_size >= copy_size); /* no overflow */
25259  copy_size = (duk_uint_t) target_length - target_ustart;
25260  }
25261 
25262  DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
25263  (unsigned long) target_ustart, (unsigned long) source_ustart,
25264  (unsigned long) copy_size));
25265 
25266  DUK_ASSERT(copy_size >= 1);
25267  DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
25268  DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
25269  DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
25270  DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
25271 
25272  /* Ensure copy is covered by underlying buffers. */
25273  DUK_ASSERT(h_bufarg->buf != NULL); /* length check */
25274  DUK_ASSERT(h_this->buf != NULL); /* length check */
25275  if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
25276  DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
25277  /* Must use memmove() because copy area may overlap (source and target
25278  * buffer may be the same, or from different slices.
25279  */
25280  DUK_MEMMOVE((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
25281  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
25282  (size_t) copy_size);
25283  } else {
25284  DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
25285  }
25286 
25287  silent_ignore:
25288  /* Return value is like write(), number of bytes written.
25289  * The return value matters because of code like:
25290  * "off += buf.copy(...)".
25291  */
25292  duk_push_uint(ctx, copy_size);
25293  return 1;
25294 
25295  fail_bounds:
25296  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
25297 }
25298 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25299 
25300 /*
25301  * TypedArray.prototype.set()
25302  *
25303  * TypedArray set() is pretty interesting to implement because:
25304  *
25305  * - The source argument may be a plain array or a typedarray. If the
25306  * source is a TypedArray, values are decoded and re-encoded into the
25307  * target (not as a plain byte copy). This may happen even when the
25308  * element byte size is the same, e.g. integer values may be re-encoded
25309  * into floats.
25310  *
25311  * - Source and target may refer to the same underlying buffer, so that
25312  * the set() operation may overlap. The specification requires that this
25313  * must work as if a copy was made before the operation. Note that this
25314  * is NOT a simple memmove() situation because the source and target
25315  * byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
25316  * expand to a 16-byte target (Uint32Array) so that the target overlaps
25317  * the source both from beginning and the end (unlike in typical memmove).
25318  *
25319  * - Even if 'buf' pointers of the source and target differ, there's no
25320  * guarantee that their memory areas don't overlap. This may be the
25321  * case with external buffers.
25322  *
25323  * Even so, it is nice to optimize for the common case:
25324  *
25325  * - Source and target separate buffers or non-overlapping.
25326  *
25327  * - Source and target have a compatible type so that a plain byte copy
25328  * is possible. Note that while e.g. uint8 and int8 are compatible
25329  * (coercion one way or another doesn't change the byte representation),
25330  * e.g. int8 and uint8clamped are NOT compatible when writing int8
25331  * values into uint8clamped typedarray (-1 would clamp to 0 for instance).
25332  *
25333  * See test-bi-typedarray-proto-set.js.
25334  */
25335 
25336 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25337 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
25338  duk_hthread *thr;
25339  duk_hbufobj *h_this;
25340  duk_hobject *h_obj;
25341  duk_uarridx_t i, n;
25342  duk_int_t offset_signed;
25343  duk_uint_t offset_elems;
25344  duk_uint_t offset_bytes;
25345 
25346  thr = (duk_hthread *) ctx;
25347  DUK_UNREF(thr);
25348 
25349  h_this = duk__require_bufobj_this(ctx);
25350  DUK_ASSERT(h_this != NULL);
25351  DUK_ASSERT_HBUFOBJ_VALID(h_this);
25352 
25353  if (h_this->buf == NULL) {
25354  DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
25355  return 0;
25356  }
25357 
25358  duk_hbufobj_promote_plain(ctx, 0);
25359  h_obj = duk_known_hobject(ctx, 0);
25360 
25361  /* XXX: V8 throws a TypeError for negative values. Would it
25362  * be more useful to interpret negative offsets here from the
25363  * end of the buffer too?
25364  */
25365  offset_signed = duk_to_int(ctx, 1);
25366  if (offset_signed < 0) {
25367  /* For some reason this is a TypeError (at least in V8). */
25368  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
25369  }
25370  offset_elems = (duk_uint_t) offset_signed;
25371  offset_bytes = offset_elems << h_this->shift;
25372  if ((offset_bytes >> h_this->shift) != offset_elems) {
25373  /* Byte length would overflow. */
25374  /* XXX: easier check with less code? */
25375  goto fail_args;
25376  }
25377  if (offset_bytes > h_this->length) {
25378  /* Equality may be OK but >length not. Checking
25379  * this explicitly avoids some overflow cases
25380  * below.
25381  */
25382  goto fail_args;
25383  }
25384  DUK_ASSERT(offset_bytes <= h_this->length);
25385 
25386  /* Fast path: source is a TypedArray (or any bufobj). */
25387 
25388  if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
25389  duk_hbufobj *h_bufarg;
25390 #if !defined(DUK_USE_PREFER_SIZE)
25391  duk_uint16_t comp_mask;
25392 #endif
25393  duk_small_int_t no_overlap = 0;
25394  duk_uint_t src_length;
25395  duk_uint_t dst_length;
25396  duk_uint_t dst_length_elems;
25397  duk_uint8_t *p_src_base;
25398  duk_uint8_t *p_src_end;
25399  duk_uint8_t *p_src;
25400  duk_uint8_t *p_dst_base;
25401  duk_uint8_t *p_dst;
25402  duk_small_uint_t src_elem_size;
25403  duk_small_uint_t dst_elem_size;
25404 
25405  h_bufarg = (duk_hbufobj *) h_obj;
25406  DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
25407 
25408  if (h_bufarg->buf == NULL) {
25409  DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
25410  return 0;
25411  }
25412 
25413  /* Nominal size check. */
25414  src_length = h_bufarg->length; /* bytes in source */
25415  dst_length_elems = (src_length >> h_bufarg->shift); /* elems in source and dest */
25416  dst_length = dst_length_elems << h_this->shift; /* bytes in dest */
25417  if ((dst_length >> h_this->shift) != dst_length_elems) {
25418  /* Byte length would overflow. */
25419  /* XXX: easier check with less code? */
25420  goto fail_args;
25421  }
25422  DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
25423  (long) src_length, (long) dst_length));
25424  DUK_ASSERT(offset_bytes <= h_this->length);
25425  if (dst_length > h_this->length - offset_bytes) {
25426  /* Overflow not an issue because subtraction is used on the right
25427  * side and guaranteed to be >= 0.
25428  */
25429  DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
25430  goto fail_args;
25431  }
25432  if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
25433  DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
25434  return 0;
25435  }
25436 
25437  p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
25438  p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
25439 
25440  /* Check actual underlying buffers for validity and that they
25441  * cover the copy. No side effects are allowed after the check
25442  * so that the validity status doesn't change.
25443  */
25444  if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
25445  !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
25446  /* The condition could be more narrow and check for the
25447  * copy area only, but there's no need for fine grained
25448  * behavior when the underlying buffer is misconfigured.
25449  */
25450  DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
25451  return 0;
25452  }
25453 
25454  /* We want to do a straight memory copy if possible: this is
25455  * an important operation because .set() is the TypedArray
25456  * way to copy chunks of memory. However, because set()
25457  * conceptually works in terms of elements, not all views are
25458  * compatible with direct byte copying.
25459  *
25460  * If we do manage a direct copy, the "overlap issue" handled
25461  * below can just be solved using memmove() because the source
25462  * and destination element sizes are necessarily equal.
25463  */
25464 
25465 #if !defined(DUK_USE_PREFER_SIZE)
25466  DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
25467  comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
25468  if (comp_mask & (1 << h_bufarg->elem_type)) {
25469  DUK_ASSERT(src_length == dst_length);
25470 
25471  DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
25472  DUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
25473  return 0;
25474  }
25475  DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
25476 #endif /* !DUK_USE_PREFER_SIZE */
25477 
25478  /* We want to avoid making a copy to process set() but that's
25479  * not always possible: the source and the target may overlap
25480  * and because element sizes are different, the overlap cannot
25481  * always be handled with a memmove() or choosing the copy
25482  * direction in a certain way. For example, if source type is
25483  * uint8 and target type is uint32, the target area may exceed
25484  * the source area from both ends!
25485  *
25486  * Note that because external buffers may point to the same
25487  * memory areas, we must ultimately make this check using
25488  * pointers.
25489  *
25490  * NOTE: careful with side effects: any side effect may cause
25491  * a buffer resize (or external buffer pointer/length update)!
25492  */
25493 
25494  DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
25495  "p_dst_base=%p, dst_length=%ld",
25496  (void *) p_src_base, (long) src_length,
25497  (void *) p_dst_base, (long) dst_length));
25498 
25499  if (p_src_base >= p_dst_base + dst_length || /* source starts after dest ends */
25500  p_src_base + src_length <= p_dst_base) { /* source ends before dest starts */
25501  no_overlap = 1;
25502  }
25503 
25504  if (!no_overlap) {
25505  /* There's overlap: the desired end result is that
25506  * conceptually a copy is made to avoid "trampling"
25507  * of source data by destination writes. We make
25508  * an actual temporary copy to handle this case.
25509  */
25510  duk_uint8_t *p_src_copy;
25511 
25512  DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
25513  p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, src_length);
25514  DUK_ASSERT(p_src_copy != NULL);
25515  DUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
25516 
25517  p_src_base = p_src_copy; /* use p_src_base from now on */
25518  }
25519  /* Value stack intentionally mixed size here. */
25520 
25521  DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
25522  "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
25523  (void *) p_src_base, (long) src_length,
25524  (void *) p_dst_base, (long) dst_length,
25525  (long) duk_get_top(ctx)));
25526 
25527  /* Ready to make the copy. We must proceed element by element
25528  * and must avoid any side effects that might cause the buffer
25529  * validity check above to become invalid.
25530  *
25531  * Although we work through the value stack here, only plain
25532  * numbers are handled which should be side effect safe.
25533  */
25534 
25535  src_elem_size = 1 << h_bufarg->shift;
25536  dst_elem_size = 1 << h_this->shift;
25537  p_src = p_src_base;
25538  p_dst = p_dst_base;
25539  p_src_end = p_src_base + src_length;
25540 
25541  while (p_src != p_src_end) {
25542  DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
25543  "p_src=%p, p_src_end=%p, p_dst=%p",
25544  (void *) p_src, (void *) p_src_end, (void *) p_dst));
25545  /* A validated read() is always a number, so it's write coercion
25546  * is always side effect free an won't invalidate pointers etc.
25547  */
25548  duk_hbufobj_push_validated_read(ctx, h_bufarg, p_src, src_elem_size);
25549  duk_hbufobj_validated_write(ctx, h_this, p_dst, dst_elem_size);
25550  duk_pop(ctx);
25551  p_src += src_elem_size;
25552  p_dst += dst_elem_size;
25553  }
25554 
25555  return 0;
25556  } else {
25557  /* Slow path: quite slow, but we save space by using the property code
25558  * to write coerce target values. We don't need to worry about overlap
25559  * here because the source is not a TypedArray.
25560  *
25561  * We could use the bufobj write coercion helper but since the
25562  * property read may have arbitrary side effects, full validity checks
25563  * would be needed for every element anyway.
25564  */
25565 
25566  n = (duk_uarridx_t) duk_get_length(ctx, 0);
25567  DUK_ASSERT(offset_bytes <= h_this->length);
25568  if ((n << h_this->shift) > h_this->length - offset_bytes) {
25569  /* Overflow not an issue because subtraction is used on the right
25570  * side and guaranteed to be >= 0.
25571  */
25572  DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
25573  goto fail_args;
25574  }
25575 
25576  /* There's no need to check for buffer validity status for the
25577  * target here: the property access code will do that for each
25578  * element. Moreover, if we did check the validity here, side
25579  * effects from reading the source argument might invalidate
25580  * the results anyway.
25581  */
25582 
25583  DUK_ASSERT_TOP(ctx, 2);
25584  duk_push_this(ctx);
25585 
25586  for (i = 0; i < n; i++) {
25587  duk_get_prop_index(ctx, 0, i);
25588  duk_put_prop_index(ctx, 2, offset_elems + i);
25589  }
25590  }
25591 
25592  return 0;
25593 
25594  fail_args:
25595  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
25596 }
25597 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25598 
25599 /*
25600  * Node.js Buffer.prototype.slice([start], [end])
25601  * ArrayBuffer.prototype.slice(begin, [end])
25602  * TypedArray.prototype.subarray(begin, [end])
25603  *
25604  * The API calls are almost identical; negative indices are counted from end
25605  * of buffer, and final indices are clamped (allowing crossed indices). Main
25606  * differences:
25607  *
25608  * - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
25609  * views, ArrayBuffer .slice() creates a copy
25610  *
25611  * - Resulting object has a different class and prototype depending on the
25612  * call (or 'this' argument)
25613  *
25614  * - TypedArray .subarray() arguments are element indices, not byte offsets
25615  *
25616  * - Plain buffer argument creates a plain buffer slice
25617  */
25618 
25619 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25620 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_context *ctx, duk_hbuffer *h_val) {
25621  duk_hthread *thr;
25622  duk_int_t start_offset, end_offset;
25623  duk_uint_t slice_length;
25624  duk_uint8_t *p_copy;
25625  duk_size_t copy_length;
25626 
25627  thr = (duk_hthread *) ctx;
25628  DUK_UNREF(thr);
25629 
25630  duk__clamp_startend_negidx_shifted(ctx,
25631  (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
25632  0 /*buffer_shift*/,
25633  0 /*idx_start*/,
25634  1 /*idx_end*/,
25635  &start_offset,
25636  &end_offset);
25637  DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
25638  DUK_ASSERT(start_offset >= 0);
25639  DUK_ASSERT(end_offset >= start_offset);
25640  slice_length = (duk_uint_t) (end_offset - start_offset);
25641 
25642  p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, (duk_size_t) slice_length);
25643  DUK_ASSERT(p_copy != NULL);
25644  copy_length = slice_length;
25645 
25646  DUK_MEMCPY((void *) p_copy,
25647  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
25648  copy_length);
25649 }
25650 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25651 
25652 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25653 /* Shared helper for slice/subarray operation.
25654  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
25655  */
25656 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx) {
25657  duk_hthread *thr;
25658  duk_small_int_t magic;
25659  duk_small_uint_t res_class_num;
25660  duk_small_int_t res_proto_bidx;
25661  duk_hbufobj *h_this;
25662  duk_hbufobj *h_bufobj;
25663  duk_hbuffer *h_val;
25664  duk_int_t start_offset, end_offset;
25665  duk_uint_t slice_length;
25666  duk_tval *tv;
25667 
25668  thr = (duk_hthread *) ctx;
25669  DUK_UNREF(thr);
25670 
25671  /* [ start end ] */
25672 
25673  magic = duk_get_current_magic(ctx);
25674 
25675  tv = duk_get_borrowed_this_tval(ctx);
25676  DUK_ASSERT(tv != NULL);
25677 
25678  if (DUK_TVAL_IS_BUFFER(tv)) {
25679  /* For plain buffers return a plain buffer slice. */
25680  h_val = DUK_TVAL_GET_BUFFER(tv);
25681  DUK_ASSERT(h_val != NULL);
25682 
25683  if (magic & 0x02) {
25684  /* Make copy: ArrayBuffer.prototype.slice() uses this. */
25685  duk__arraybuffer_plain_slice(ctx, h_val);
25686  return 1;
25687  } else {
25688  /* View into existing buffer: cannot be done if the
25689  * result is a plain buffer because there's no slice
25690  * info. So return an ArrayBuffer instance; coerce
25691  * the 'this' binding into an object and behave as if
25692  * the original call was for an Object-coerced plain
25693  * buffer (handled automatically by duk__require_bufobj_this()).
25694  */
25695 
25696  DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
25697  /* fall through */
25698  }
25699  }
25700  tv = NULL; /* No longer valid nor needed. */
25701 
25702  h_this = duk__require_bufobj_this(ctx);
25703 
25704  /* Slice offsets are element (not byte) offsets, which only matters
25705  * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
25706  * zero so byte and element offsets are the same. Negative indices
25707  * are counted from end of slice, crossed indices are allowed (and
25708  * result in zero length result), and final values are clamped
25709  * against the current slice. There's intentionally no check
25710  * against the underlying buffer here.
25711  */
25712 
25713  duk__clamp_startend_negidx_shifted(ctx,
25714  (duk_int_t) h_this->length,
25715  (duk_uint8_t) h_this->shift,
25716  0 /*idx_start*/,
25717  1 /*idx_end*/,
25718  &start_offset,
25719  &end_offset);
25720  DUK_ASSERT(end_offset >= start_offset);
25721  slice_length = (duk_uint_t) (end_offset - start_offset);
25722 
25723  /* The resulting buffer object gets the same class and prototype as
25724  * the buffer in 'this', e.g. if the input is a Uint8Array the
25725  * result is a Uint8Array; if the input is a Float32Array, the
25726  * result is a Float32Array. The result internal prototype should
25727  * be the default prototype for the class (e.g. initial value of
25728  * Uint8Array.prototype), not copied from the argument (Duktape 1.x
25729  * did that).
25730  *
25731  * Node.js Buffers have special handling: they're Uint8Arrays as far
25732  * as the internal class is concerned, so the new Buffer should also
25733  * be an Uint8Array but inherit from Buffer.prototype.
25734  */
25735  res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
25736  DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN); /* type check guarantees */
25737  DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
25738  res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
25739  if (magic & 0x04) {
25740  res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
25741  }
25742  h_bufobj = duk_push_bufobj_raw(ctx,
25743  DUK_HOBJECT_FLAG_EXTENSIBLE |
25744  DUK_HOBJECT_FLAG_BUFOBJ |
25745  DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
25746  res_proto_bidx);
25747  DUK_ASSERT(h_bufobj != NULL);
25748 
25749  h_bufobj->length = slice_length;
25750  h_bufobj->shift = h_this->shift; /* inherit */
25751  h_bufobj->elem_type = h_this->elem_type; /* inherit */
25752  h_bufobj->is_typedarray = magic & 0x01;
25753  DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
25754 
25755  h_val = h_this->buf;
25756  if (h_val == NULL) {
25757  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
25758  }
25759 
25760  if (magic & 0x02) {
25761  /* non-zero: make copy */
25762  duk_uint8_t *p_copy;
25763  duk_size_t copy_length;
25764 
25765  p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(ctx, (duk_size_t) slice_length); /* must be zeroed, not all bytes always copied */
25766  DUK_ASSERT(p_copy != NULL);
25767 
25768  /* Copy slice, respecting underlying buffer limits; remainder
25769  * is left as zero.
25770  */
25771  copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
25772  DUK_MEMCPY((void *) p_copy,
25773  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
25774  copy_length);
25775 
25776  h_val = duk_known_hbuffer(ctx, -1);
25777 
25778  h_bufobj->buf = h_val;
25779  DUK_HBUFFER_INCREF(thr, h_val);
25780  DUK_ASSERT(h_bufobj->offset == 0);
25781 
25782  duk_pop(ctx); /* reachable so pop OK */
25783  } else {
25784  h_bufobj->buf = h_val;
25785  DUK_HBUFFER_INCREF(thr, h_val);
25786  h_bufobj->offset = (duk_uint_t) (h_this->offset + start_offset);
25787 
25788  /* Copy the .buffer property, needed for TypedArray.prototype.subarray().
25789  *
25790  * XXX: limit copy only for TypedArray classes specifically?
25791  */
25792 
25793  DUK_ASSERT(h_bufobj->buf_prop == NULL);
25794  h_bufobj->buf_prop = h_this->buf_prop; /* may be NULL */
25795  DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
25796  }
25797  /* unbalanced stack on purpose */
25798 
25799  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
25800  return 1;
25801 }
25802 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25803 
25804 /*
25805  * Node.js Buffer.isEncoding()
25806  */
25807 
25808 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25809 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx) {
25810  const char *encoding;
25811 
25812  /* only accept lowercase 'utf8' now. */
25813 
25814  encoding = duk_to_string(ctx, 0);
25815  DUK_ASSERT(duk_is_string(ctx, 0)); /* guaranteed by duk_to_string() */
25816  duk_push_boolean(ctx, DUK_STRCMP(encoding, "utf8") == 0);
25817  return 1;
25818 }
25819 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25820 
25821 /*
25822  * Node.js Buffer.isBuffer()
25823  */
25824 
25825 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25826 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx) {
25827  duk_hthread *thr;
25828  duk_hobject *h;
25829  duk_hobject *h_proto;
25830  duk_bool_t ret = 0;
25831 
25832  thr = (duk_hthread *) ctx;
25833 
25834  DUK_ASSERT(duk_get_top(ctx) >= 1); /* nargs */
25835  h = duk_get_hobject(ctx, 0);
25836  if (h != NULL) {
25837  h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
25838  DUK_ASSERT(h_proto != NULL);
25839 
25840  h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
25841  if (h != NULL) {
25842  ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
25843  }
25844  }
25845 
25846  duk_push_boolean(ctx, ret);
25847  return 1;
25848 }
25849 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25850 
25851 /*
25852  * Node.js Buffer.byteLength()
25853  */
25854 
25855 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25856 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx) {
25857  const char *str;
25858  duk_size_t len;
25859 
25860  /* At the moment Buffer(<str>) will just use the string bytes as
25861  * is (ignoring encoding), so we return the string length here
25862  * unconditionally.
25863  */
25864 
25865  /* XXX: to be revised; Old Node.js behavior just coerces any buffer
25866  * values to string:
25867  * $ node
25868  * > Buffer.byteLength(new Uint32Array(10))
25869  * 20
25870  * > Buffer.byteLength(new Uint32Array(100))
25871  * 20
25872  * (The 20 comes from '[object Uint32Array]'.length
25873  */
25874 
25875  str = duk_to_lstring(ctx, 0, &len);
25876  DUK_UNREF(str);
25877  duk_push_size_t(ctx, len);
25878  return 1;
25879 }
25880 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25881 
25882 /*
25883  * Node.js Buffer.concat()
25884  */
25885 
25886 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25887 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx) {
25888  duk_hthread *thr;
25889  duk_hobject *h_arg;
25890  duk_int_t total_length = 0;
25891  duk_hbufobj *h_bufobj;
25892  duk_hbufobj *h_bufres;
25893  duk_hbuffer *h_val;
25894  duk_uint_t i, n;
25895  duk_uint8_t *p;
25896  duk_size_t space_left;
25897  duk_size_t copy_size;
25898 
25899  thr = (duk_hthread *) ctx;
25900  DUK_UNREF(thr);
25901 
25902  /* Node.js accepts only actual Arrays. */
25903  h_arg = duk_require_hobject(ctx, 0);
25904  if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
25905  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
25906  }
25907 
25908  /* Compute result length and validate argument buffers. */
25909  n = (duk_uint_t) duk_get_length(ctx, 0);
25910  for (i = 0; i < n; i++) {
25911  /* Neutered checks not necessary here: neutered buffers have
25912  * zero 'length' so we'll effectively skip them.
25913  */
25914  DUK_ASSERT_TOP(ctx, 2); /* [ array totalLength ] */
25915  duk_get_prop_index(ctx, 0, (duk_uarridx_t) i); /* -> [ array totalLength buf ] */
25916  h_bufobj = duk__require_bufobj_value(ctx, 2);
25917  DUK_ASSERT(h_bufobj != NULL);
25918  total_length += h_bufobj->length;
25919  duk_pop(ctx);
25920  }
25921  /* In Node.js v0.12.1 a 1-element array is special and won't create a
25922  * copy, this was fixed later so an explicit check no longer needed.
25923  */
25924 
25925  /* User totalLength overrides a computed length, but we'll check
25926  * every copy in the copy loop. Note that duk_to_uint() can
25927  * technically have arbitrary side effects so we need to recheck
25928  * the buffers in the copy loop.
25929  */
25930  if (!duk_is_undefined(ctx, 1) && n > 0) {
25931  /* For n == 0, Node.js ignores totalLength argument and
25932  * returns a zero length buffer.
25933  */
25934  total_length = duk_to_int(ctx, 1);
25935  }
25936  if (total_length < 0) {
25937  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
25938  }
25939 
25940  h_bufres = duk_push_bufobj_raw(ctx,
25941  DUK_HOBJECT_FLAG_EXTENSIBLE |
25942  DUK_HOBJECT_FLAG_BUFOBJ |
25943  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
25944  DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
25945  DUK_ASSERT(h_bufres != NULL);
25946 
25947  p = (duk_uint8_t *) duk_push_fixed_buffer_zero(ctx, total_length); /* must be zeroed, all bytes not necessarily written over */
25948  DUK_ASSERT(p != NULL);
25949  space_left = total_length;
25950 
25951  for (i = 0; i < n; i++) {
25952  DUK_ASSERT_TOP(ctx, 4); /* [ array totalLength bufres buf ] */
25953 
25954  duk_get_prop_index(ctx, 0, (duk_uarridx_t) i);
25955  h_bufobj = duk__require_bufobj_value(ctx, 4);
25956  DUK_ASSERT(h_bufobj != NULL);
25957 
25958  copy_size = h_bufobj->length;
25959  if (copy_size > space_left) {
25960  copy_size = space_left;
25961  }
25962 
25963  if (h_bufobj->buf != NULL &&
25964  DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
25965  DUK_MEMCPY((void *) p,
25966  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
25967  copy_size);
25968  } else {
25969  /* Just skip, leaving zeroes in the result. */
25970  ;
25971  }
25972  p += copy_size;
25973  space_left -= copy_size;
25974 
25975  duk_pop(ctx);
25976  }
25977 
25978  h_val = duk_known_hbuffer(ctx, -1);
25979 
25980  duk__set_bufobj_buffer(ctx, h_bufres, h_val);
25981  h_bufres->is_typedarray = 1;
25982  DUK_ASSERT_HBUFOBJ_VALID(h_bufres);
25983 
25984  duk_pop(ctx); /* pop plain buffer, now reachable through h_bufres */
25985 
25986  return 1; /* return h_bufres */
25987 }
25988 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
25989 
25990 /*
25991  * Shared readfield and writefield methods
25992  *
25993  * The readfield/writefield methods need support for endianness and field
25994  * types. All offsets are byte based so no offset shifting is needed.
25995  */
25996 
25997 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
25998 /* Format of magic, bits:
25999  * 0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
26000  * 3: endianness: 0=little, 1=big
26001  * 4: signed: 1=yes, 0=no
26002  * 5: typedarray: 1=yes, 0=no
26003  */
26004 #define DUK__FLD_8BIT 0
26005 #define DUK__FLD_16BIT 1
26006 #define DUK__FLD_32BIT 2
26007 #define DUK__FLD_FLOAT 3
26008 #define DUK__FLD_DOUBLE 4
26009 #define DUK__FLD_VARINT 5
26010 #define DUK__FLD_BIGENDIAN (1 << 3)
26011 #define DUK__FLD_SIGNED (1 << 4)
26012 #define DUK__FLD_TYPEDARRAY (1 << 5)
26013 
26014 /* XXX: split into separate functions for each field type? */
26015 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx) {
26016  duk_hthread *thr;
26017  duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
26018  duk_small_int_t magic_ftype;
26019  duk_small_int_t magic_bigendian;
26020  duk_small_int_t magic_signed;
26021  duk_small_int_t magic_typedarray;
26022  duk_small_int_t endswap;
26023  duk_hbufobj *h_this;
26024  duk_bool_t no_assert;
26025  duk_int_t offset_signed;
26026  duk_uint_t offset;
26027  duk_uint_t buffer_length;
26028  duk_uint_t check_length;
26029  duk_uint8_t *buf;
26030  duk_double_union du;
26031 
26032  thr = (duk_hthread *) ctx;
26033  DUK_UNREF(thr);
26034 
26035  magic_ftype = magic & 0x0007;
26036  magic_bigendian = magic & 0x0008;
26037  magic_signed = magic & 0x0010;
26038  magic_typedarray = magic & 0x0020;
26039 
26040  h_this = duk__require_bufobj_this(ctx); /* XXX: very inefficient for plain buffers */
26041  DUK_ASSERT(h_this != NULL);
26042  buffer_length = h_this->length;
26043 
26044  /* [ offset noAssert ], when ftype != DUK__FLD_VARINT */
26045  /* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
26046  /* [ offset littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
26047 
26048  /* Handle TypedArray vs. Node.js Buffer arg differences */
26049  if (magic_typedarray) {
26050  no_assert = 0;
26051 #if defined(DUK_USE_INTEGER_LE)
26052  endswap = !duk_to_boolean(ctx, 1); /* 1=little endian */
26053 #else
26054  endswap = duk_to_boolean(ctx, 1); /* 1=little endian */
26055 #endif
26056  } else {
26057  no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
26058 #if defined(DUK_USE_INTEGER_LE)
26059  endswap = magic_bigendian;
26060 #else
26061  endswap = !magic_bigendian;
26062 #endif
26063  }
26064 
26065  /* Offset is coerced first to signed integer range and then to unsigned.
26066  * This ensures we can add a small byte length (1-8) to the offset in
26067  * bound checks and not wrap.
26068  */
26069  offset_signed = duk_to_int(ctx, 0);
26070  offset = (duk_uint_t) offset_signed;
26071  if (offset_signed < 0) {
26072  goto fail_bounds;
26073  }
26074 
26075  DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
26076  "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
26077  "endswap=%d",
26078  (long) buffer_length, (long) offset, (int) no_assert,
26079  (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
26080  (int) (magic_signed >> 4), (int) endswap));
26081 
26082  /* Update 'buffer_length' to be the effective, safe limit which
26083  * takes into account the underlying buffer. This value will be
26084  * potentially invalidated by any side effect.
26085  */
26086  check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
26087  DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
26088  (long) buffer_length, (long) check_length));
26089 
26090  if (h_this->buf) {
26091  buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
26092  } else {
26093  /* Neutered. We could go into the switch-case safely with
26094  * buf == NULL because check_length == 0. To avoid scanbuild
26095  * warnings, fail directly instead.
26096  */
26097  DUK_ASSERT(check_length == 0);
26098  goto fail_neutered;
26099  }
26100  DUK_ASSERT(buf != NULL);
26101 
26102  switch (magic_ftype) {
26103  case DUK__FLD_8BIT: {
26104  duk_uint8_t tmp;
26105  if (offset + 1U > check_length) {
26106  goto fail_bounds;
26107  }
26108  tmp = buf[offset];
26109  if (magic_signed) {
26110  duk_push_int(ctx, (duk_int_t) ((duk_int8_t) tmp));
26111  } else {
26112  duk_push_uint(ctx, (duk_uint_t) tmp);
26113  }
26114  break;
26115  }
26116  case DUK__FLD_16BIT: {
26117  duk_uint16_t tmp;
26118  if (offset + 2U > check_length) {
26119  goto fail_bounds;
26120  }
26121  DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);
26122  tmp = du.us[0];
26123  if (endswap) {
26124  tmp = DUK_BSWAP16(tmp);
26125  }
26126  if (magic_signed) {
26127  duk_push_int(ctx, (duk_int_t) ((duk_int16_t) tmp));
26128  } else {
26129  duk_push_uint(ctx, (duk_uint_t) tmp);
26130  }
26131  break;
26132  }
26133  case DUK__FLD_32BIT: {
26134  duk_uint32_t tmp;
26135  if (offset + 4U > check_length) {
26136  goto fail_bounds;
26137  }
26138  DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
26139  tmp = du.ui[0];
26140  if (endswap) {
26141  tmp = DUK_BSWAP32(tmp);
26142  }
26143  if (magic_signed) {
26144  duk_push_int(ctx, (duk_int_t) ((duk_int32_t) tmp));
26145  } else {
26146  duk_push_uint(ctx, (duk_uint_t) tmp);
26147  }
26148  break;
26149  }
26150  case DUK__FLD_FLOAT: {
26151  duk_uint32_t tmp;
26152  if (offset + 4U > check_length) {
26153  goto fail_bounds;
26154  }
26155  DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);
26156  if (endswap) {
26157  tmp = du.ui[0];
26158  tmp = DUK_BSWAP32(tmp);
26159  du.ui[0] = tmp;
26160  }
26161  duk_push_number(ctx, (duk_double_t) du.f[0]);
26162  break;
26163  }
26164  case DUK__FLD_DOUBLE: {
26165  if (offset + 8U > check_length) {
26166  goto fail_bounds;
26167  }
26168  DUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);
26169  if (endswap) {
26170  DUK_DBLUNION_BSWAP64(&du);
26171  }
26172  duk_push_number(ctx, (duk_double_t) du.d);
26173  break;
26174  }
26175  case DUK__FLD_VARINT: {
26176  /* Node.js Buffer variable width integer field. We don't really
26177  * care about speed here, so aim for shortest algorithm.
26178  */
26179  duk_int_t field_bytelen;
26180  duk_int_t i, i_step, i_end;
26181 #if defined(DUK_USE_64BIT_OPS)
26182  duk_int64_t tmp;
26183  duk_small_uint_t shift_tmp;
26184 #else
26185  duk_double_t tmp;
26186  duk_small_int_t highbyte;
26187 #endif
26188  const duk_uint8_t *p;
26189 
26190  field_bytelen = duk_get_int(ctx, 1); /* avoid side effects! */
26191  if (field_bytelen < 1 || field_bytelen > 6) {
26192  goto fail_field_length;
26193  }
26194  if (offset + (duk_uint_t) field_bytelen > check_length) {
26195  goto fail_bounds;
26196  }
26197  p = (const duk_uint8_t *) (buf + offset);
26198 
26199  /* Slow gathering of value using either 64-bit arithmetic
26200  * or IEEE doubles if 64-bit types not available. Handling
26201  * of negative numbers is a bit non-obvious in both cases.
26202  */
26203 
26204  if (magic_bigendian) {
26205  /* Gather in big endian */
26206  i = 0;
26207  i_step = 1;
26208  i_end = field_bytelen; /* one i_step over */
26209  } else {
26210  /* Gather in little endian */
26211  i = field_bytelen - 1;
26212  i_step = -1;
26213  i_end = -1; /* one i_step over */
26214  }
26215 
26216 #if defined(DUK_USE_64BIT_OPS)
26217  tmp = 0;
26218  do {
26219  DUK_ASSERT(i >= 0 && i < field_bytelen);
26220  tmp = (tmp << 8) + (duk_int64_t) p[i];
26221  i += i_step;
26222  } while (i != i_end);
26223 
26224  if (magic_signed) {
26225  /* Shift to sign extend. */
26226  shift_tmp = 64 - (field_bytelen * 8);
26227  tmp = (tmp << shift_tmp) >> shift_tmp;
26228  }
26229 
26230  duk_push_i64(ctx, tmp);
26231 #else
26232  highbyte = p[i];
26233  if (magic_signed && (highbyte & 0x80) != 0) {
26234  /* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
26235  tmp = (duk_double_t) (highbyte - 256);
26236  } else {
26237  tmp = (duk_double_t) highbyte;
26238  }
26239  for (;;) {
26240  i += i_step;
26241  if (i == i_end) {
26242  break;
26243  }
26244  DUK_ASSERT(i >= 0 && i < field_bytelen);
26245  tmp = (tmp * 256.0) + (duk_double_t) p[i];
26246  }
26247 
26248  duk_push_number(ctx, tmp);
26249 #endif
26250  break;
26251  }
26252  default: { /* should never happen but default here */
26253  goto fail_bounds;
26254  }
26255  }
26256 
26257  return 1;
26258 
26259  fail_neutered:
26260  fail_field_length:
26261  fail_bounds:
26262  if (no_assert) {
26263  /* Node.js return value for noAssert out-of-bounds reads is
26264  * usually (but not always) NaN. Return NaN consistently.
26265  */
26266  duk_push_nan(ctx);
26267  return 1;
26268  }
26269  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
26270 }
26271 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
26272 
26273 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26274 /* XXX: split into separate functions for each field type? */
26275 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx) {
26276  duk_hthread *thr;
26277  duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(ctx);
26278  duk_small_int_t magic_ftype;
26279  duk_small_int_t magic_bigendian;
26280  duk_small_int_t magic_signed;
26281  duk_small_int_t magic_typedarray;
26282  duk_small_int_t endswap;
26283  duk_hbufobj *h_this;
26284  duk_bool_t no_assert;
26285  duk_int_t offset_signed;
26286  duk_uint_t offset;
26287  duk_uint_t buffer_length;
26288  duk_uint_t check_length;
26289  duk_uint8_t *buf;
26290  duk_double_union du;
26291  duk_int_t nbytes = 0;
26292 
26293  thr = (duk_hthread *) ctx;
26294  DUK_UNREF(thr);
26295 
26296  magic_ftype = magic & 0x0007;
26297  magic_bigendian = magic & 0x0008;
26298  magic_signed = magic & 0x0010;
26299  magic_typedarray = magic & 0x0020;
26300  DUK_UNREF(magic_signed);
26301 
26302  h_this = duk__require_bufobj_this(ctx); /* XXX: very inefficient for plain buffers */
26303  DUK_ASSERT(h_this != NULL);
26304  buffer_length = h_this->length;
26305 
26306  /* [ value offset noAssert ], when ftype != DUK__FLD_VARINT */
26307  /* [ value offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
26308  /* [ offset value littleEndian ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
26309 
26310  /* Handle TypedArray vs. Node.js Buffer arg differences */
26311  if (magic_typedarray) {
26312  no_assert = 0;
26313 #if defined(DUK_USE_INTEGER_LE)
26314  endswap = !duk_to_boolean(ctx, 2); /* 1=little endian */
26315 #else
26316  endswap = duk_to_boolean(ctx, 2); /* 1=little endian */
26317 #endif
26318  duk_swap(ctx, 0, 1); /* offset/value order different from Node.js */
26319  } else {
26320  no_assert = duk_to_boolean(ctx, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
26321 #if defined(DUK_USE_INTEGER_LE)
26322  endswap = magic_bigendian;
26323 #else
26324  endswap = !magic_bigendian;
26325 #endif
26326  }
26327 
26328  /* Offset is coerced first to signed integer range and then to unsigned.
26329  * This ensures we can add a small byte length (1-8) to the offset in
26330  * bound checks and not wrap.
26331  */
26332  offset_signed = duk_to_int(ctx, 1);
26333  offset = (duk_uint_t) offset_signed;
26334 
26335  /* We need 'nbytes' even for a failed offset; return value must be
26336  * (offset + nbytes) even when write fails due to invalid offset.
26337  */
26338  if (magic_ftype != DUK__FLD_VARINT) {
26339  DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
26340  nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
26341  } else {
26342  nbytes = duk_get_int(ctx, 2);
26343  if (nbytes < 1 || nbytes > 6) {
26344  goto fail_field_length;
26345  }
26346  }
26347  DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
26348 
26349  /* Now we can check offset validity. */
26350  if (offset_signed < 0) {
26351  goto fail_bounds;
26352  }
26353 
26354  DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
26355  "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
26356  "endswap=%d",
26357  duk_get_tval(ctx, 0), (long) buffer_length, (long) offset, (int) no_assert,
26358  (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
26359  (int) (magic_signed >> 4), (int) endswap));
26360 
26361  /* Coerce value to a number before computing check_length, so that
26362  * the field type specific coercion below can't have side effects
26363  * that would invalidate check_length.
26364  */
26365  duk_to_number(ctx, 0);
26366 
26367  /* Update 'buffer_length' to be the effective, safe limit which
26368  * takes into account the underlying buffer. This value will be
26369  * potentially invalidated by any side effect.
26370  */
26371  check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
26372  DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
26373  (long) buffer_length, (long) check_length));
26374 
26375  if (h_this->buf) {
26376  buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
26377  } else {
26378  /* Neutered. We could go into the switch-case safely with
26379  * buf == NULL because check_length == 0. To avoid scanbuild
26380  * warnings, fail directly instead.
26381  */
26382  DUK_ASSERT(check_length == 0);
26383  goto fail_neutered;
26384  }
26385  DUK_ASSERT(buf != NULL);
26386 
26387  switch (magic_ftype) {
26388  case DUK__FLD_8BIT: {
26389  if (offset + 1U > check_length) {
26390  goto fail_bounds;
26391  }
26392  /* sign doesn't matter when writing */
26393  buf[offset] = (duk_uint8_t) duk_to_uint32(ctx, 0);
26394  break;
26395  }
26396  case DUK__FLD_16BIT: {
26397  duk_uint16_t tmp;
26398  if (offset + 2U > check_length) {
26399  goto fail_bounds;
26400  }
26401  tmp = (duk_uint16_t) duk_to_uint32(ctx, 0);
26402  if (endswap) {
26403  tmp = DUK_BSWAP16(tmp);
26404  }
26405  du.us[0] = tmp;
26406  /* sign doesn't matter when writing */
26407  DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);
26408  break;
26409  }
26410  case DUK__FLD_32BIT: {
26411  duk_uint32_t tmp;
26412  if (offset + 4U > check_length) {
26413  goto fail_bounds;
26414  }
26415  tmp = (duk_uint32_t) duk_to_uint32(ctx, 0);
26416  if (endswap) {
26417  tmp = DUK_BSWAP32(tmp);
26418  }
26419  du.ui[0] = tmp;
26420  /* sign doesn't matter when writing */
26421  DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
26422  break;
26423  }
26424  case DUK__FLD_FLOAT: {
26425  duk_uint32_t tmp;
26426  if (offset + 4U > check_length) {
26427  goto fail_bounds;
26428  }
26429  du.f[0] = (duk_float_t) duk_to_number(ctx, 0);
26430  if (endswap) {
26431  tmp = du.ui[0];
26432  tmp = DUK_BSWAP32(tmp);
26433  du.ui[0] = tmp;
26434  }
26435  /* sign doesn't matter when writing */
26436  DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);
26437  break;
26438  }
26439  case DUK__FLD_DOUBLE: {
26440  if (offset + 8U > check_length) {
26441  goto fail_bounds;
26442  }
26443  du.d = (duk_double_t) duk_to_number(ctx, 0);
26444  if (endswap) {
26445  DUK_DBLUNION_BSWAP64(&du);
26446  }
26447  /* sign doesn't matter when writing */
26448  DUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);
26449  break;
26450  }
26451  case DUK__FLD_VARINT: {
26452  /* Node.js Buffer variable width integer field. We don't really
26453  * care about speed here, so aim for shortest algorithm.
26454  */
26455  duk_int_t field_bytelen;
26456  duk_int_t i, i_step, i_end;
26457 #if defined(DUK_USE_64BIT_OPS)
26458  duk_int64_t tmp;
26459 #else
26460  duk_double_t tmp;
26461 #endif
26462  duk_uint8_t *p;
26463 
26464  field_bytelen = (duk_int_t) nbytes;
26465  if (offset + (duk_uint_t) field_bytelen > check_length) {
26466  goto fail_bounds;
26467  }
26468 
26469  /* Slow writing of value using either 64-bit arithmetic
26470  * or IEEE doubles if 64-bit types not available. There's
26471  * no special sign handling when writing varints.
26472  */
26473 
26474  if (magic_bigendian) {
26475  /* Write in big endian */
26476  i = field_bytelen; /* one i_step added at top of loop */
26477  i_step = -1;
26478  i_end = 0;
26479  } else {
26480  /* Write in little endian */
26481  i = -1; /* one i_step added at top of loop */
26482  i_step = 1;
26483  i_end = field_bytelen - 1;
26484  }
26485 
26486  /* XXX: The duk_to_number() cast followed by integer coercion
26487  * is platform specific so NaN, +/- Infinity, and out-of-bounds
26488  * values result in platform specific output now.
26489  * See: test-bi-nodejs-buffer-proto-varint-special.js
26490  */
26491 
26492 #if defined(DUK_USE_64BIT_OPS)
26493  tmp = (duk_int64_t) duk_to_number(ctx, 0);
26494  p = (duk_uint8_t *) (buf + offset);
26495  do {
26496  i += i_step;
26497  DUK_ASSERT(i >= 0 && i < field_bytelen);
26498  p[i] = (duk_uint8_t) (tmp & 0xff);
26499  tmp = tmp >> 8; /* unnecessary shift for last byte */
26500  } while (i != i_end);
26501 #else
26502  tmp = duk_to_number(ctx, 0);
26503  p = (duk_uint8_t *) (buf + offset);
26504  do {
26505  i += i_step;
26506  tmp = DUK_FLOOR(tmp);
26507  DUK_ASSERT(i >= 0 && i < field_bytelen);
26508  p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
26509  tmp = tmp / 256.0; /* unnecessary div for last byte */
26510  } while (i != i_end);
26511 #endif
26512  break;
26513  }
26514  default: { /* should never happen but default here */
26515  goto fail_bounds;
26516  }
26517  }
26518 
26519  /* Node.js Buffer: return offset + #bytes written (i.e. next
26520  * write offset).
26521  */
26522  if (magic_typedarray) {
26523  /* For TypedArrays 'undefined' return value is specified
26524  * by ES2015 (matches V8).
26525  */
26526  return 0;
26527  }
26528  duk_push_uint(ctx, offset + nbytes);
26529  return 1;
26530 
26531  fail_neutered:
26532  fail_field_length:
26533  fail_bounds:
26534  if (no_assert) {
26535  /* Node.js return value for failed writes is offset + #bytes
26536  * that would have been written.
26537  */
26538  /* XXX: for negative input offsets, 'offset' will be a large
26539  * positive value so the result here is confusing.
26540  */
26541  if (magic_typedarray) {
26542  return 0;
26543  }
26544  duk_push_uint(ctx, offset + nbytes);
26545  return 1;
26546  }
26547  DUK_DCERROR_RANGE_INVALID_ARGS(thr);
26548 }
26549 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
26550 
26551 /*
26552  * Accessors for .buffer, .byteLength, .byteOffset
26553  */
26554 
26555 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26556 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx) {
26557  duk_hbufobj *h_bufobj;
26558 
26559  h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(ctx, DUK__BUFOBJ_FLAG_THROW /*flags*/);
26560  DUK_ASSERT(h_bufobj != NULL);
26561  if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
26562  duk_hbufobj *h_res;
26563  duk_hbuffer *h_buf;
26564 
26565  h_buf = (duk_hbuffer *) h_bufobj;
26566  h_res = duk_push_bufobj_raw(ctx,
26567  DUK_HOBJECT_FLAG_EXTENSIBLE |
26568  DUK_HOBJECT_FLAG_BUFOBJ |
26569  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
26570  DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
26571  DUK_ASSERT(h_res != NULL);
26572  DUK_UNREF(h_res);
26573 
26574  duk__set_bufobj_buffer(ctx, h_res, h_buf);
26575  DUK_ASSERT_HBUFOBJ_VALID(h_res);
26576 
26577  DUK_DD(DUK_DDPRINT("autospawned .buffer ArrayBuffer: %!iT", duk_get_tval(ctx, -1)));
26578  return 1;
26579  } else {
26580  if (h_bufobj->buf_prop) {
26581  duk_push_hobject(ctx, h_bufobj->buf_prop);
26582  return 1;
26583  }
26584  }
26585  return 0;
26586 }
26587 
26588 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx) {
26589  duk_hbufobj *h_bufobj;
26590 
26591  h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(ctx, DUK__BUFOBJ_FLAG_THROW /*flags*/);
26592  DUK_ASSERT(h_bufobj != NULL);
26593  if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
26594  duk_push_uint(ctx, 0);
26595  } else {
26596  /* If neutered must return 0; offset is zeroed during
26597  * neutering.
26598  */
26599  duk_push_uint(ctx, h_bufobj->offset);
26600  }
26601  return 1;
26602 }
26603 
26604 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx) {
26605  duk_hbufobj *h_bufobj;
26606 
26607  h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(ctx, DUK__BUFOBJ_FLAG_THROW /*flags*/);
26608  DUK_ASSERT(h_bufobj != NULL);
26609  if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
26610  duk_hbuffer *h_buf;
26611 
26612  h_buf = (duk_hbuffer *) h_bufobj;
26613  DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX); /* Buffer limits. */
26614  duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
26615  } else {
26616  /* If neutered must return 0; length is zeroed during
26617  * neutering.
26618  */
26619  duk_push_uint(ctx, h_bufobj->length);
26620  }
26621  return 1;
26622 }
26623 #else /* DUK_USE_BUFFEROBJECT_SUPPORT */
26624 /* No .buffer getter without ArrayBuffer support. */
26625 #if 0
26626 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx) {
26627  return 0;
26628 }
26629 #endif
26630 
26631 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx) {
26632  duk_push_uint(ctx, 0);
26633  return 1;
26634 }
26635 
26636 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx) {
26637  duk_hbuffer *h_buf;
26638 
26639  /* XXX: helper? */
26640  duk_push_this(ctx);
26641  h_buf = duk_require_hbuffer(ctx, -1);
26642  duk_push_uint(ctx, DUK_HBUFFER_GET_SIZE(h_buf));
26643  return 1;
26644 }
26645 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
26646 
26647 /* automatic undefs */
26648 #undef DUK__BUFOBJ_FLAG_PROMOTE
26649 #undef DUK__BUFOBJ_FLAG_THROW
26650 #undef DUK__FLD_16BIT
26651 #undef DUK__FLD_32BIT
26652 #undef DUK__FLD_8BIT
26653 #undef DUK__FLD_BIGENDIAN
26654 #undef DUK__FLD_DOUBLE
26655 #undef DUK__FLD_FLOAT
26656 #undef DUK__FLD_SIGNED
26657 #undef DUK__FLD_TYPEDARRAY
26658 #undef DUK__FLD_VARINT
26659 /*
26660  * Date built-ins
26661  *
26662  * Unlike most built-ins, Date has some platform dependencies for getting
26663  * UTC time, converting between UTC and local time, and parsing and
26664  * formatting time values. These are all abstracted behind DUK_USE_xxx
26665  * config options. There are built-in platform specific providers for
26666  * POSIX and Windows, but external providers can also be used.
26667  *
26668  * See doc/datetime.rst.
26669  *
26670  */
26671 
26672 /* #include duk_internal.h -> already included */
26673 
26674 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
26675 
26676 /*
26677  * Forward declarations
26678  */
26679 
26680 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);
26681 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags);
26682 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val);
26683 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags);
26684 
26685 /*
26686  * Other file level defines
26687  */
26688 
26689 /* Debug macro to print all parts and dparts (used manually because of debug level). */
26690 #define DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts) do { \
26691  DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
26692  (long) (parts)[0], (long) (parts)[1], \
26693  (long) (parts)[2], (long) (parts)[3], \
26694  (long) (parts)[4], (long) (parts)[5], \
26695  (long) (parts)[6], (long) (parts)[7], \
26696  (double) (dparts)[0], (double) (dparts)[1], \
26697  (double) (dparts)[2], (double) (dparts)[3], \
26698  (double) (dparts)[4], (double) (dparts)[5], \
26699  (double) (dparts)[6], (double) (dparts)[7])); \
26700  } while (0)
26701 #define DUK__DPRINT_PARTS(parts) do { \
26702  DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
26703  (long) (parts)[0], (long) (parts)[1], \
26704  (long) (parts)[2], (long) (parts)[3], \
26705  (long) (parts)[4], (long) (parts)[5], \
26706  (long) (parts)[6], (long) (parts)[7])); \
26707  } while (0)
26708 #define DUK__DPRINT_DPARTS(dparts) do { \
26709  DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
26710  (double) (dparts)[0], (double) (dparts)[1], \
26711  (double) (dparts)[2], (double) (dparts)[3], \
26712  (double) (dparts)[4], (double) (dparts)[5], \
26713  (double) (dparts)[6], (double) (dparts)[7])); \
26714  } while (0)
26715 
26716 /* Equivalent year for DST calculations outside [1970,2038[ range, see
26717  * E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and
26718  * starts with the same weekday on Jan 1.
26719  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
26720  */
26721 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
26722 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
26723 #if 1
26724  /* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
26725  * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
26726  */
26727 
26728  /* non-leap year: sunday, monday, ... */
26729  DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
26730  DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
26731 
26732  /* leap year: sunday, monday, ... */
26733  DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
26734  DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
26735 #endif
26736 
26737 #if 0
26738  /* This is based on Rhino EquivalentYear() algorithm:
26739  * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
26740  */
26741 
26742  /* non-leap year: sunday, monday, ... */
26743  DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
26744  DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
26745 
26746  /* leap year: sunday, monday, ... */
26747  DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
26748  DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
26749 #endif
26750 };
26751 
26752 /*
26753  * ISO 8601 subset parser.
26754  */
26755 
26756 /* Parser part count. */
26757 #define DUK__NUM_ISO8601_PARSER_PARTS 9
26758 
26759 /* Parser part indices. */
26760 #define DUK__PI_YEAR 0
26761 #define DUK__PI_MONTH 1
26762 #define DUK__PI_DAY 2
26763 #define DUK__PI_HOUR 3
26764 #define DUK__PI_MINUTE 4
26765 #define DUK__PI_SECOND 5
26766 #define DUK__PI_MILLISECOND 6
26767 #define DUK__PI_TZHOUR 7
26768 #define DUK__PI_TZMINUTE 8
26769 
26770 /* Parser part masks. */
26771 #define DUK__PM_YEAR (1 << DUK__PI_YEAR)
26772 #define DUK__PM_MONTH (1 << DUK__PI_MONTH)
26773 #define DUK__PM_DAY (1 << DUK__PI_DAY)
26774 #define DUK__PM_HOUR (1 << DUK__PI_HOUR)
26775 #define DUK__PM_MINUTE (1 << DUK__PI_MINUTE)
26776 #define DUK__PM_SECOND (1 << DUK__PI_SECOND)
26777 #define DUK__PM_MILLISECOND (1 << DUK__PI_MILLISECOND)
26778 #define DUK__PM_TZHOUR (1 << DUK__PI_TZHOUR)
26779 #define DUK__PM_TZMINUTE (1 << DUK__PI_TZMINUTE)
26780 
26781 /* Parser separator indices. */
26782 #define DUK__SI_PLUS 0
26783 #define DUK__SI_MINUS 1
26784 #define DUK__SI_T 2
26785 #define DUK__SI_SPACE 3
26786 #define DUK__SI_COLON 4
26787 #define DUK__SI_PERIOD 5
26788 #define DUK__SI_Z 6
26789 #define DUK__SI_NUL 7
26790 
26791 /* Parser separator masks. */
26792 #define DUK__SM_PLUS (1 << DUK__SI_PLUS)
26793 #define DUK__SM_MINUS (1 << DUK__SI_MINUS)
26794 #define DUK__SM_T (1 << DUK__SI_T)
26795 #define DUK__SM_SPACE (1 << DUK__SI_SPACE)
26796 #define DUK__SM_COLON (1 << DUK__SI_COLON)
26797 #define DUK__SM_PERIOD (1 << DUK__SI_PERIOD)
26798 #define DUK__SM_Z (1 << DUK__SI_Z)
26799 #define DUK__SM_NUL (1 << DUK__SI_NUL)
26800 
26801 /* Rule control flags. */
26802 #define DUK__CF_NEG (1 << 0) /* continue matching, set neg_tzoffset flag */
26803 #define DUK__CF_ACCEPT (1 << 1) /* accept string */
26804 #define DUK__CF_ACCEPT_NUL (1 << 2) /* accept string if next char is NUL (otherwise reject) */
26805 
26806 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags) \
26807  ((duk_uint32_t) (partmask) + \
26808  (((duk_uint32_t) (sepmask)) << 9) + \
26809  (((duk_uint32_t) (nextpart)) << 17) + \
26810  (((duk_uint32_t) (flags)) << 21))
26811 
26812 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags) do { \
26813  (var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
26814  (var_flags) = (duk_small_uint_t) ((rule) >> 21); \
26815  } while (0)
26816 
26817 #define DUK__RULE_MASK_PART_SEP 0x1ffffUL
26818 
26819 /* Matching separator index is used in the control table */
26820 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
26821  DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
26822  DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
26823 };
26824 
26825 /* Rule table: first matching rule is used to determine what to do next. */
26826 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
26827  DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
26828  DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
26829  DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
26830  DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
26831  DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
26832  DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
26833  DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
26834  DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_PLUS, DUK__PI_TZHOUR, 0),
26835  DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_MINUS, DUK__PI_TZHOUR, DUK__CF_NEG),
26836  DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_Z, 0, DUK__CF_ACCEPT_NUL),
26837  DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE, DUK__SM_NUL, 0, DUK__CF_ACCEPT)
26838 
26839  /* Note1: the specification doesn't require matching a time form with
26840  * just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
26841  *
26842  * Note2: the specification doesn't require matching a timezone offset
26843  * with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
26844  */
26845 };
26846 
26847 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_context *ctx, const char *str) {
26848  duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
26849  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
26850  duk_double_t d;
26851  const duk_uint8_t *p;
26852  duk_small_uint_t part_idx = 0;
26853  duk_int_t accum = 0;
26854  duk_small_uint_t ndigits = 0;
26855  duk_bool_t neg_year = 0;
26856  duk_bool_t neg_tzoffset = 0;
26857  duk_uint_fast8_t ch;
26858  duk_small_uint_t i;
26859 
26860  /* During parsing, month and day are one-based; set defaults here. */
26861  DUK_MEMZERO(parts, sizeof(parts));
26862  DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0); /* don't care value, year is mandatory */
26863  parts[DUK_DATE_IDX_MONTH] = 1;
26864  parts[DUK_DATE_IDX_DAY] = 1;
26865 
26866  /* Special handling for year sign. */
26867  p = (const duk_uint8_t *) str;
26868  ch = p[0];
26869  if (ch == DUK_ASC_PLUS) {
26870  p++;
26871  } else if (ch == DUK_ASC_MINUS) {
26872  neg_year = 1;
26873  p++;
26874  }
26875 
26876  for (;;) {
26877  ch = *p++;
26878  DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
26879  (long) part_idx, (long) ch,
26880  (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
26881 
26882  if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
26883  if (ndigits >= 9) {
26884  DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
26885  goto reject;
26886  }
26887  if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
26888  /* ignore millisecond fractions after 3 */
26889  } else {
26890  accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
26891  ndigits++;
26892  }
26893  } else {
26894  duk_uint_fast32_t match_val;
26895  duk_small_int_t sep_idx;
26896 
26897  if (ndigits <= 0) {
26898  goto reject;
26899  }
26900  if (part_idx == DUK__PI_MILLISECOND) {
26901  /* complete the millisecond field */
26902  while (ndigits < 3) {
26903  accum *= 10;
26904  ndigits++;
26905  }
26906  }
26907  parts[part_idx] = accum;
26908  DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
26909 
26910  accum = 0;
26911  ndigits = 0;
26912 
26913  for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
26914  if (duk__parse_iso8601_seps[i] == ch) {
26915  break;
26916  }
26917  }
26918  if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
26919  DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
26920  goto reject;
26921  }
26922 
26923  sep_idx = i;
26924  match_val = (1UL << part_idx) + (1UL << (sep_idx + 9)); /* match against rule part/sep bits */
26925 
26926  for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
26927  duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
26928  duk_small_uint_t nextpart;
26929  duk_small_uint_t cflags;
26930 
26931  DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
26932  (long) part_idx, (long) sep_idx,
26933  (unsigned long) match_val, (unsigned long) rule));
26934 
26935  if ((rule & match_val) != match_val) {
26936  continue;
26937  }
26938 
26939  DUK__UNPACK_RULE(rule, nextpart, cflags);
26940 
26941  DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
26942  "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
26943  (long) part_idx, (long) sep_idx,
26944  (unsigned long) match_val, (unsigned long) rule,
26945  (long) nextpart, (unsigned long) cflags));
26946 
26947  if (cflags & DUK__CF_NEG) {
26948  neg_tzoffset = 1;
26949  }
26950 
26951  if (cflags & DUK__CF_ACCEPT) {
26952  goto accept;
26953  }
26954 
26955  if (cflags & DUK__CF_ACCEPT_NUL) {
26956  DUK_ASSERT(*(p - 1) != (char) 0);
26957  if (*p == DUK_ASC_NUL) {
26958  goto accept;
26959  }
26960  goto reject;
26961  }
26962 
26963  part_idx = nextpart;
26964  break;
26965  } /* rule match */
26966 
26967  if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
26968  DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
26969  goto reject;
26970  }
26971 
26972  if (ch == 0) {
26973  /* This shouldn't be necessary, but check just in case
26974  * to avoid any chance of overruns.
26975  */
26976  DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
26977  goto reject;
26978  }
26979  } /* if-digit-else-ctrl */
26980  } /* char loop */
26981 
26982  /* We should never exit the loop above. */
26983  DUK_UNREACHABLE();
26984 
26985  reject:
26986  DUK_DDD(DUK_DDDPRINT("reject"));
26987  return 0;
26988 
26989  accept:
26990  DUK_DDD(DUK_DDDPRINT("accept"));
26991 
26992  /* Apply timezone offset to get the main parts in UTC */
26993  if (neg_year) {
26994  parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
26995  }
26996  if (neg_tzoffset) {
26997  parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
26998  parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
26999  } else {
27000  parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
27001  parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
27002  }
27003  parts[DUK__PI_MONTH] -= 1; /* zero-based month */
27004  parts[DUK__PI_DAY] -= 1; /* zero-based day */
27005 
27006  /* Use double parts, they tolerate unnormalized time.
27007  *
27008  * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
27009  * on purpose. It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
27010  * but will make the value initialized just in case, and avoid any
27011  * potential for Valgrind issues.
27012  */
27013  for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
27014  DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
27015  dparts[i] = parts[i];
27016  }
27017 
27018  d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
27019  duk_push_number(ctx, d);
27020  return 1;
27021 }
27022 
27023 /*
27024  * Date/time parsing helper.
27025  *
27026  * Parse a datetime string into a time value. We must first try to parse
27027  * the input according to the standard format in E5.1 Section 15.9.1.15.
27028  * If that fails, we can try to parse using custom parsing, which can
27029  * either be platform neutral (custom code) or platform specific (using
27030  * existing platform API calls).
27031  *
27032  * Note in particular that we must parse whatever toString(), toUTCString(),
27033  * and toISOString() can produce; see E5.1 Section 15.9.4.2.
27034  *
27035  * Returns 1 to allow tail calling.
27036  *
27037  * There is much room for improvement here with respect to supporting
27038  * alternative datetime formats. For instance, V8 parses '2012-01-01' as
27039  * UTC and '2012/01/01' as local time.
27040  */
27041 
27042 DUK_LOCAL duk_ret_t duk__parse_string(duk_context *ctx, const char *str) {
27043  /* XXX: there is a small risk here: because the ISO 8601 parser is
27044  * very loose, it may end up parsing some datetime values which
27045  * would be better parsed with a platform specific parser.
27046  */
27047 
27048  DUK_ASSERT(str != NULL);
27049  DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
27050 
27051  if (duk__parse_string_iso8601_subset(ctx, str) != 0) {
27052  return 1;
27053  }
27054 
27055 #if defined(DUK_USE_DATE_PARSE_STRING)
27056  /* Contract, either:
27057  * - Push value on stack and return 1
27058  * - Don't push anything on stack and return 0
27059  */
27060 
27061  if (DUK_USE_DATE_PARSE_STRING(ctx, str) != 0) {
27062  return 1;
27063  }
27064 #else
27065  /* No platform-specific parsing, this is not an error. */
27066 #endif
27067 
27068  duk_push_nan(ctx);
27069  return 1;
27070 }
27071 
27072 /*
27073  * Calendar helpers
27074  *
27075  * Some helpers are used for getters and can operate on normalized values
27076  * which can be represented with 32-bit signed integers. Other helpers are
27077  * needed by setters and operate on un-normalized double values, must watch
27078  * out for non-finite numbers etc.
27079  */
27080 
27081 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
27082  (duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
27083  (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
27084  (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
27085 };
27086 
27087 /* Maximum iteration count for computing UTC-to-local time offset when
27088  * creating an Ecmascript time value from local parts.
27089  */
27090 #define DUK__LOCAL_TZOFFSET_MAXITER 4
27091 
27092 /* Because 'day since epoch' can be negative and is used to compute weekday
27093  * using a modulo operation, add this multiple of 7 to avoid negative values
27094  * when year is below 1970 epoch. Ecmascript time values are restricted to
27095  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
27096  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
27097  */
27098 #define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
27099 
27100 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
27101  if ((year % 4) != 0) {
27102  return 0;
27103  }
27104  if ((year % 100) != 0) {
27105  return 1;
27106  }
27107  if ((year % 400) != 0) {
27108  return 0;
27109  }
27110  return 1;
27111 }
27112 
27113 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
27114  return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
27115 }
27116 
27117 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
27118  return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
27119 }
27120 
27121 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
27122  return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
27123 }
27124 
27125 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
27126  if (!DUK_ISFINITE(x)) {
27127  return DUK_DOUBLE_NAN;
27128  }
27129 
27130  if (!duk_bi_date_timeval_in_valid_range(x)) {
27131  return DUK_DOUBLE_NAN;
27132  }
27133 
27134  x = duk_js_tointeger_number(x);
27135 
27136  /* Here we'd have the option to normalize -0 to +0. */
27137  return x;
27138 }
27139 
27140 /* Integer division which floors also negative values correctly. */
27141 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
27142  DUK_ASSERT(b > 0);
27143  if (a >= 0) {
27144  return a / b;
27145  } else {
27146  /* e.g. a = -4, b = 5 --> -4 - 5 + 1 / 5 --> -8 / 5 --> -1
27147  * a = -5, b = 5 --> -5 - 5 + 1 / 5 --> -9 / 5 --> -1
27148  * a = -6, b = 5 --> -6 - 5 + 1 / 5 --> -10 / 5 --> -2
27149  */
27150  return (a - b + 1) / b;
27151  }
27152 }
27153 
27154 /* Compute day number of the first day of a given year. */
27155 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
27156  /* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
27157  * values, but is incorrect for negative ones.
27158  */
27159  return 365 * (year - 1970)
27160  + duk__div_floor(year - 1969, 4)
27161  - duk__div_floor(year - 1901, 100)
27162  + duk__div_floor(year - 1601, 400);
27163 }
27164 
27165 /* Given a day number, determine year and day-within-year. */
27166 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
27167  duk_int_t year;
27168  duk_int_t diff_days;
27169 
27170  /* estimate year upwards (towards positive infinity), then back down;
27171  * two iterations should be enough
27172  */
27173 
27174  if (day >= 0) {
27175  year = 1970 + day / 365;
27176  } else {
27177  year = 1970 + day / 366;
27178  }
27179 
27180  for (;;) {
27181  diff_days = duk__day_from_year(year) - day;
27182  DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
27183  if (diff_days <= 0) {
27184  DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
27185  *out_day_within_year = -diff_days;
27186  DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
27187  (long) year, (long) *out_day_within_year));
27188  DUK_ASSERT(*out_day_within_year >= 0);
27189  DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
27190  return year;
27191  }
27192 
27193  /* Note: this is very tricky; we must never 'overshoot' the
27194  * correction downwards.
27195  */
27196  year -= 1 + (diff_days - 1) / 366; /* conservative */
27197  }
27198 }
27199 
27200 /* Given a (year, month, day-within-month) triple, compute day number.
27201  * The input triple is un-normalized and may contain non-finite values.
27202  */
27203 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
27204  duk_int_t day_num;
27205  duk_bool_t is_leap;
27206  duk_small_int_t i, n;
27207 
27208  /* Assume that year, month, day are all coerced to whole numbers.
27209  * They may also be NaN or infinity, in which case this function
27210  * must return NaN or infinity to ensure time value becomes NaN.
27211  * If 'day' is NaN, the final return will end up returning a NaN,
27212  * so it doesn't need to be checked here.
27213  */
27214 
27215  if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
27216  return DUK_DOUBLE_NAN;
27217  }
27218 
27219  year += DUK_FLOOR(month / 12.0);
27220 
27221  month = DUK_FMOD(month, 12.0);
27222  if (month < 0.0) {
27223  /* handle negative values */
27224  month += 12.0;
27225  }
27226 
27227  /* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
27228  * does not normalize the day-of-month (nor check whether or not
27229  * it is finite) because it's not necessary for finding the day
27230  * number which matches the (year,month) pair.
27231  *
27232  * We assume that duk__day_from_year() is exact here.
27233  *
27234  * Without an explicit infinity / NaN check in the beginning,
27235  * day_num would be a bogus integer here.
27236  *
27237  * It's possible for 'year' to be out of integer range here.
27238  * If so, we need to return NaN without integer overflow.
27239  * This fixes test-bug-setyear-overflow.js.
27240  */
27241 
27242  if (!duk_bi_date_year_in_valid_range(year)) {
27243  DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
27244  return DUK_DOUBLE_NAN;
27245  }
27246  day_num = duk__day_from_year((duk_int_t) year);
27247  is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
27248 
27249  n = (duk_small_int_t) month;
27250  for (i = 0; i < n; i++) {
27251  day_num += duk__days_in_month[i];
27252  if (i == 1 && is_leap) {
27253  day_num++;
27254  }
27255  }
27256 
27257  /* If 'day' is NaN, returns NaN. */
27258  return (duk_double_t) day_num + day;
27259 }
27260 
27261 /* Split time value into parts. The time value is assumed to be an internal
27262  * one, i.e. finite, no fractions. Possible local time adjustment has already
27263  * been applied when reading the time value.
27264  */
27265 DUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {
27266  duk_double_t d1, d2;
27267  duk_int_t t1, t2;
27268  duk_int_t day_since_epoch;
27269  duk_int_t year; /* does not fit into 16 bits */
27270  duk_small_int_t day_in_year;
27271  duk_small_int_t month;
27272  duk_small_int_t day;
27273  duk_small_int_t dim;
27274  duk_int_t jan1_since_epoch;
27275  duk_small_int_t jan1_weekday;
27276  duk_int_t equiv_year;
27277  duk_small_uint_t i;
27278  duk_bool_t is_leap;
27279  duk_small_int_t arridx;
27280 
27281  DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
27282  DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions in internal time */
27283 
27284  /* The timevalue must be in valid Ecmascript range, but since a local
27285  * time offset can be applied, we need to allow a +/- 24h leeway to
27286  * the value. In other words, although the UTC time is within the
27287  * Ecmascript range, the local part values can be just outside of it.
27288  */
27289  DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
27290  DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
27291 
27292  /* these computations are guaranteed to be exact for the valid
27293  * E5 time value range, assuming milliseconds without fractions.
27294  */
27295  d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
27296  if (d1 < 0.0) {
27297  /* deal with negative values */
27298  d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
27299  }
27300  d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
27301  DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
27302  /* now expected to fit into a 32-bit integer */
27303  t1 = (duk_int_t) d1;
27304  t2 = (duk_int_t) d2;
27305  day_since_epoch = t2;
27306  DUK_ASSERT((duk_double_t) t1 == d1);
27307  DUK_ASSERT((duk_double_t) t2 == d2);
27308 
27309  /* t1 = milliseconds within day (fits 32 bit)
27310  * t2 = day number from epoch (fits 32 bit, may be negative)
27311  */
27312 
27313  parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
27314  parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
27315  parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
27316  parts[DUK_DATE_IDX_HOUR] = t1;
27317  DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
27318  DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
27319  DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
27320  DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
27321 
27322  DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
27323  (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
27324  (long) parts[DUK_DATE_IDX_HOUR],
27325  (long) parts[DUK_DATE_IDX_MINUTE],
27326  (long) parts[DUK_DATE_IDX_SECOND],
27327  (long) parts[DUK_DATE_IDX_MILLISECOND]));
27328 
27329  /* This assert depends on the input parts representing time inside
27330  * the Ecmascript range.
27331  */
27332  DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
27333  parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
27334  DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
27335 
27336  year = duk__year_from_day(t2, &day_in_year);
27337  day = day_in_year;
27338  is_leap = duk_bi_date_is_leap_year(year);
27339  for (month = 0; month < 12; month++) {
27340  dim = duk__days_in_month[month];
27341  if (month == 1 && is_leap) {
27342  dim++;
27343  }
27344  DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
27345  (long) month, (long) dim, (long) day));
27346  if (day < dim) {
27347  break;
27348  }
27349  day -= dim;
27350  }
27351  DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
27352  DUK_ASSERT(month >= 0 && month <= 11);
27353  DUK_ASSERT(day >= 0 && day <= 31);
27354 
27355  /* Equivalent year mapping, used to avoid DST trouble when platform
27356  * may fail to provide reasonable DST answers for dates outside the
27357  * ordinary range (e.g. 1970-2038). An equivalent year has the same
27358  * leap-year-ness as the original year and begins on the same weekday
27359  * (Jan 1).
27360  *
27361  * The year 2038 is avoided because there seem to be problems with it
27362  * on some platforms. The year 1970 is also avoided as there were
27363  * practical problems with it; an equivalent year is used for it too,
27364  * which breaks some DST computations for 1970 right now, see e.g.
27365  * test-bi-date-tzoffset-brute-fi.js.
27366  */
27367  if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
27368  DUK_ASSERT(is_leap == 0 || is_leap == 1);
27369 
27370  jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
27371  DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
27372  jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
27373  DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
27374  arridx = jan1_weekday;
27375  if (is_leap) {
27376  arridx += 7;
27377  }
27378  DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
27379 
27380  equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
27381  year = equiv_year;
27382  DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
27383  "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
27384  (long) year, (long) day_in_year, (long) day_since_epoch,
27385  (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
27386  }
27387 
27388  parts[DUK_DATE_IDX_YEAR] = year;
27389  parts[DUK_DATE_IDX_MONTH] = month;
27390  parts[DUK_DATE_IDX_DAY] = day;
27391 
27392  if (flags & DUK_DATE_FLAG_ONEBASED) {
27393  parts[DUK_DATE_IDX_MONTH]++; /* zero-based -> one-based */
27394  parts[DUK_DATE_IDX_DAY]++; /* -""- */
27395  }
27396 
27397  if (dparts != NULL) {
27398  for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
27399  dparts[i] = (duk_double_t) parts[i];
27400  }
27401  }
27402 }
27403 
27404 /* Compute time value from (double) parts. The parts can be either UTC
27405  * or local time; if local, they need to be (conceptually) converted into
27406  * UTC time. The parts may represent valid or invalid time, and may be
27407  * wildly out of range (but may cancel each other and still come out in
27408  * the valid Date range).
27409  */
27410 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
27411 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
27412  /* See comments below on MakeTime why these are volatile. */
27413  volatile duk_double_t tmp_time;
27414  volatile duk_double_t tmp_day;
27415  volatile duk_double_t d;
27416 #else
27417  duk_double_t tmp_time;
27418  duk_double_t tmp_day;
27419  duk_double_t d;
27420 #endif
27421  duk_small_uint_t i;
27422  duk_int_t tzoff, tzoffprev1, tzoffprev2;
27423 
27424  /* Expects 'this' at top of stack on entry. */
27425 
27426  /* Coerce all finite parts with ToInteger(). ToInteger() must not
27427  * be called for NaN/Infinity because it will convert e.g. NaN to
27428  * zero. If ToInteger() has already been called, this has no side
27429  * effects and is idempotent.
27430  *
27431  * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
27432  * issues if the value is uninitialized.
27433  */
27434  for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
27435  /* SCANBUILD: scan-build complains here about assigned value
27436  * being garbage or undefined. This is correct but operating
27437  * on undefined values has no ill effect and is ignored by the
27438  * caller in the case where this happens.
27439  */
27440  d = dparts[i];
27441  if (DUK_ISFINITE(d)) {
27442  dparts[i] = duk_js_tointeger_number(d);
27443  }
27444  }
27445 
27446  /* Use explicit steps in computation to try to ensure that
27447  * computation happens with intermediate results coerced to
27448  * double values (instead of using something more accurate).
27449  * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
27450  * rules (= Ecmascript '+' and '*' operators).
27451  *
27452  * Without 'volatile' even this approach fails on some platform
27453  * and compiler combinations. For instance, gcc 4.8.1 on Ubuntu
27454  * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
27455  * would fail because of some optimizations when computing tmp_time
27456  * (MakeTime below). Adding 'volatile' to tmp_time solved this
27457  * particular problem (annoyingly, also adding debug prints or
27458  * running the executable under valgrind hides it).
27459  */
27460 
27461  /* MakeTime */
27462  tmp_time = 0.0;
27463  tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
27464  tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
27465  tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
27466  tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
27467 
27468  /* MakeDay */
27469  tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
27470 
27471  /* MakeDate */
27472  d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
27473 
27474  DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
27475  (double) tmp_time, (double) tmp_day, (double) d));
27476 
27477  /* Optional UTC conversion. */
27478  if (flags & DUK_DATE_FLAG_LOCALTIME) {
27479  /* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
27480  * time value computed from UTC parts. At this point we only
27481  * have 'd' which is a time value computed from local parts, so
27482  * it is off by the UTC-to-local time offset which we don't know
27483  * yet. The current solution for computing the UTC-to-local
27484  * time offset is to iterate a few times and detect a fixed
27485  * point or a two-cycle loop (or a sanity iteration limit),
27486  * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
27487  *
27488  * E5.1 Section 15.9.1.9:
27489  * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
27490  *
27491  * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
27492  */
27493 
27494 #if 0
27495  /* Old solution: don't iterate, incorrect */
27496  tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
27497  DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
27498  d -= tzoff * 1000L;
27499  DUK_UNREF(tzoffprev1);
27500  DUK_UNREF(tzoffprev2);
27501 #endif
27502 
27503  /* Iteration solution */
27504  tzoff = 0;
27505  tzoffprev1 = 999999999L; /* invalid value which never matches */
27506  for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
27507  tzoffprev2 = tzoffprev1;
27508  tzoffprev1 = tzoff;
27509  tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
27510  DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
27511  (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
27512  if (tzoff == tzoffprev1) {
27513  DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
27514  (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
27515  break;
27516  } else if (tzoff == tzoffprev2) {
27517  /* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
27518  * In these cases, favor a higher tzoffset to get a consistent
27519  * result which is independent of iteration count. Not sure if
27520  * this is a generically correct solution.
27521  */
27522  DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
27523  (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
27524  if (tzoffprev1 > tzoff) {
27525  tzoff = tzoffprev1;
27526  }
27527  break;
27528  }
27529  }
27530  DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
27531  d -= tzoff * 1000L;
27532  }
27533 
27534  /* TimeClip(), which also handles Infinity -> NaN conversion */
27535  d = duk__timeclip(d);
27536 
27537  return d;
27538 }
27539 
27540 /*
27541  * API oriented helpers
27542  */
27543 
27544 /* Push 'this' binding, check that it is a Date object; then push the
27545  * internal time value. At the end, stack is: [ ... this timeval ].
27546  * Returns the time value. Local time adjustment is done if requested.
27547  */
27548 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_context *ctx, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
27549  duk_hthread *thr = (duk_hthread *) ctx;
27550  duk_hobject *h;
27551  duk_double_t d;
27552  duk_int_t tzoffset = 0;
27553 
27554  duk_push_this(ctx);
27555  h = duk_get_hobject(ctx, -1); /* XXX: getter with class check, useful in built-ins */
27556  if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
27557  DUK_ERROR_TYPE(thr, "expected Date");
27558  }
27559 
27560  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
27561  d = duk_to_number_m1(ctx);
27562  duk_pop(ctx);
27563 
27564  if (DUK_ISNAN(d)) {
27565  if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
27566  d = 0.0;
27567  }
27568  if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
27569  DUK_ERROR_RANGE(thr, "Invalid Date");
27570  }
27571  }
27572  /* if no NaN handling flag, may still be NaN here, but not Inf */
27573  DUK_ASSERT(!DUK_ISINF(d));
27574 
27575  if (flags & DUK_DATE_FLAG_LOCALTIME) {
27576  /* Note: DST adjustment is determined using UTC time.
27577  * If 'd' is NaN, tzoffset will be 0.
27578  */
27579  tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d); /* seconds */
27580  d += tzoffset * 1000L;
27581  }
27582  if (out_tzoffset) {
27583  *out_tzoffset = tzoffset;
27584  }
27585 
27586  /* [ ... this ] */
27587  return d;
27588 }
27589 
27590 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_context *ctx, duk_small_uint_t flags) {
27591  return duk__push_this_get_timeval_tzoffset(ctx, flags, NULL);
27592 }
27593 
27594 /* Set timeval to 'this' from dparts, push the new time value onto the
27595  * value stack and return 1 (caller can then tail call us). Expects
27596  * the value stack to contain 'this' on the stack top.
27597  */
27598 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_context *ctx, duk_double_t *dparts, duk_small_uint_t flags) {
27599  duk_double_t d;
27600 
27601  /* [ ... this ] */
27602 
27603  d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
27604  duk_push_number(ctx, d); /* -> [ ... this timeval_new ] */
27605  duk_dup_top(ctx); /* -> [ ... this timeval_new timeval_new ] */
27606  duk_put_prop_stridx_short(ctx, -3, DUK_STRIDX_INT_VALUE);
27607 
27608  /* stack top: new time value, return 1 to allow tail calls */
27609  return 1;
27610 }
27611 
27612 /* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */
27613 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) {
27614  char yearstr[8]; /* "-123456\0" */
27615  char tzstr[8]; /* "+11:22\0" */
27616  char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
27617 
27618  DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
27619  DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
27620  DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
27621 
27622  /* Note: %06d for positive value, %07d for negative value to include
27623  * sign and 6 digits.
27624  */
27625  DUK_SNPRINTF(yearstr,
27626  sizeof(yearstr),
27627  (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
27628  ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
27629  (long) parts[DUK_DATE_IDX_YEAR]);
27630  yearstr[sizeof(yearstr) - 1] = (char) 0;
27631 
27632  if (flags & DUK_DATE_FLAG_LOCALTIME) {
27633  /* tzoffset seconds are dropped; 16 bits suffice for
27634  * time offset in minutes
27635  */
27636  if (tzoffset >= 0) {
27637  duk_small_int_t tmp = tzoffset / 60;
27638  DUK_SNPRINTF(tzstr, sizeof(tzstr), "+%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
27639  } else {
27640  duk_small_int_t tmp = -tzoffset / 60;
27641  DUK_SNPRINTF(tzstr, sizeof(tzstr), "-%02d:%02d", (int) (tmp / 60), (int) (tmp % 60));
27642  }
27643  tzstr[sizeof(tzstr) - 1] = (char) 0;
27644  } else {
27645  tzstr[0] = DUK_ASC_UC_Z;
27646  tzstr[1] = (char) 0;
27647  }
27648 
27649  /* Unlike year, the other parts fit into 16 bits so %d format
27650  * is portable.
27651  */
27652  if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
27653  DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
27654  (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
27655  (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
27656  (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
27657  } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
27658  DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
27659  (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
27660  } else {
27661  DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
27662  DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
27663  (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
27664  (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
27665  (const char *) tzstr);
27666  }
27667 }
27668 
27669 /* Helper for string conversion calls: check 'this' binding, get the
27670  * internal time value, and format date and/or time in a few formats.
27671  * Return value allows tail calls.
27672  */
27673 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags) {
27674  duk_double_t d;
27675  duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
27676  duk_int_t tzoffset; /* seconds, doesn't fit into 16 bits */
27677  duk_bool_t rc;
27678  duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
27679 
27680  DUK_UNREF(rc); /* unreferenced with some options */
27681 
27682  d = duk__push_this_get_timeval_tzoffset(ctx, flags, &tzoffset);
27683  if (DUK_ISNAN(d)) {
27684  duk_push_hstring_stridx(ctx, DUK_STRIDX_INVALID_DATE);
27685  return 1;
27686  }
27687  DUK_ASSERT(DUK_ISFINITE(d));
27688 
27689  /* formatters always get one-based month/day-of-month */
27690  duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
27691  DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
27692  DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
27693 
27694  if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
27695  /* try locale specific formatter; if it refuses to format the
27696  * string, fall back to an ISO 8601 formatted value in local
27697  * time.
27698  */
27699 #if defined(DUK_USE_DATE_FORMAT_STRING)
27700  /* Contract, either:
27701  * - Push string to value stack and return 1
27702  * - Don't push anything and return 0
27703  */
27704 
27705  rc = DUK_USE_DATE_FORMAT_STRING(ctx, parts, tzoffset, flags);
27706  if (rc != 0) {
27707  return 1;
27708  }
27709 #else
27710  /* No locale specific formatter; this is OK, we fall back
27711  * to ISO 8601.
27712  */
27713 #endif
27714  }
27715 
27716  /* Different calling convention than above used because the helper
27717  * is shared.
27718  */
27719  duk__format_parts_iso8601(parts, tzoffset, flags, buf);
27720  duk_push_string(ctx, (const char *) buf);
27721  return 1;
27722 }
27723 
27724 /* Helper for component getter calls: check 'this' binding, get the
27725  * internal time value, split it into parts (either as UTC time or
27726  * local time), push a specified component as a return value to the
27727  * value stack and return 1 (caller can then tail call us).
27728  */
27729 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) {
27730  duk_double_t d;
27731  duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
27732  duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
27733 
27734  DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
27735  DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
27736 
27737  d = duk__push_this_get_timeval(ctx, flags_and_idx);
27738  if (DUK_ISNAN(d)) {
27739  duk_push_nan(ctx);
27740  return 1;
27741  }
27742  DUK_ASSERT(DUK_ISFINITE(d));
27743 
27744  duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx); /* no need to mask idx portion */
27745 
27746  /* Setter APIs detect special year numbers (0...99) and apply a +1900
27747  * only in certain cases. The legacy getYear() getter applies -1900
27748  * unconditionally.
27749  */
27750  duk_push_int(ctx, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
27751  return 1;
27752 }
27753 
27754 /* Helper for component setter calls: check 'this' binding, get the
27755  * internal time value, split it into parts (either as UTC time or
27756  * local time), modify one or more components as specified, recompute
27757  * the time value, set it as the internal value. Finally, push the
27758  * new time value as a return value to the value stack and return 1
27759  * (caller can then tail call us).
27760  */
27761 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_and_maxnargs) {
27762  duk_double_t d;
27763  duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
27764  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
27765  duk_idx_t nargs;
27766  duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT); /* unpack args */
27767  duk_small_uint_t idx_first, idx;
27768  duk_small_uint_t i;
27769 
27770  nargs = duk_get_top(ctx);
27771  d = duk__push_this_get_timeval(ctx, flags_and_maxnargs);
27772  DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
27773 
27774  if (DUK_ISFINITE(d)) {
27775  duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
27776  } else {
27777  /* NaN timevalue: we need to coerce the arguments, but
27778  * the resulting internal timestamp needs to remain NaN.
27779  * This works but is not pretty: parts and dparts will
27780  * be partially uninitialized, but we only write to them.
27781  */
27782  }
27783 
27784  /*
27785  * Determining which datetime components to overwrite based on
27786  * stack arguments is a bit complicated, but important to factor
27787  * out from setters themselves for compactness.
27788  *
27789  * If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
27790  *
27791  * 1 -> millisecond
27792  * 2 -> second, [millisecond]
27793  * 3 -> minute, [second], [millisecond]
27794  * 4 -> hour, [minute], [second], [millisecond]
27795  *
27796  * Else:
27797  *
27798  * 1 -> date
27799  * 2 -> month, [date]
27800  * 3 -> year, [month], [date]
27801  *
27802  * By comparing nargs and maxnargs (and flags) we know which
27803  * components to override. We rely on part index ordering.
27804  */
27805 
27806  if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
27807  DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
27808  idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
27809  } else {
27810  DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
27811  idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
27812  }
27813  DUK_ASSERT_DISABLE(idx_first >= 0); /* unsigned */
27814  DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
27815 
27816  for (i = 0; i < maxnargs; i++) {
27817  if ((duk_idx_t) i >= nargs) {
27818  /* no argument given -> leave components untouched */
27819  break;
27820  }
27821  idx = idx_first + i;
27822  DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
27823  DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
27824 
27825  if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
27826  duk__twodigit_year_fixup(ctx, (duk_idx_t) i);
27827  }
27828 
27829  dparts[idx] = duk_to_number(ctx, i);
27830 
27831  if (idx == DUK_DATE_IDX_DAY) {
27832  /* Day-of-month is one-based in the API, but zero-based
27833  * internally, so fix here. Note that month is zero-based
27834  * both in the API and internally.
27835  */
27836  /* SCANBUILD: complains about use of uninitialized values.
27837  * The complaint is correct, but operating in undefined
27838  * values here is intentional in some cases and the caller
27839  * ignores the results.
27840  */
27841  dparts[idx] -= 1.0;
27842  }
27843  }
27844 
27845  /* Leaves new timevalue on stack top and returns 1, which is correct
27846  * for part setters.
27847  */
27848  if (DUK_ISFINITE(d)) {
27849  return duk__set_this_timeval_from_dparts(ctx, dparts, flags_and_maxnargs);
27850  } else {
27851  /* Internal timevalue is already NaN, so don't touch it. */
27852  duk_push_nan(ctx);
27853  return 1;
27854  }
27855 }
27856 
27857 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
27858  * 1900 and replace value at idx_val.
27859  */
27860 DUK_LOCAL void duk__twodigit_year_fixup(duk_context *ctx, duk_idx_t idx_val) {
27861  duk_double_t d;
27862 
27863  /* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
27864  * might not generate better code due to casting.
27865  */
27866 
27867  /* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
27868  duk_to_number(ctx, idx_val);
27869  if (duk_is_nan(ctx, idx_val)) {
27870  return;
27871  }
27872  duk_dup(ctx, idx_val);
27873  duk_to_int(ctx, -1);
27874  d = duk_get_number(ctx, -1); /* get as double to handle huge numbers correctly */
27875  if (d >= 0.0 && d <= 99.0) {
27876  d += 1900.0;
27877  duk_push_number(ctx, d);
27878  duk_replace(ctx, idx_val);
27879  }
27880  duk_pop(ctx);
27881 }
27882 
27883 /* Set datetime parts from stack arguments, defaulting any missing values.
27884  * Day-of-week is not set; it is not required when setting the time value.
27885  */
27886 DUK_LOCAL void duk__set_parts_from_args(duk_context *ctx, duk_double_t *dparts, duk_idx_t nargs) {
27887  duk_double_t d;
27888  duk_small_uint_t i;
27889  duk_small_uint_t idx;
27890 
27891  /* Causes a ToNumber() coercion, but doesn't break coercion order since
27892  * year is coerced first anyway.
27893  */
27894  duk__twodigit_year_fixup(ctx, 0);
27895 
27896  /* There are at most 7 args, but we use 8 here so that also
27897  * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
27898  * for any Valgrind gripes later.
27899  */
27900  for (i = 0; i < 8; i++) {
27901  /* Note: rely on index ordering */
27902  idx = DUK_DATE_IDX_YEAR + i;
27903  if ((duk_idx_t) i < nargs) {
27904  d = duk_to_number(ctx, (duk_idx_t) i);
27905  if (idx == DUK_DATE_IDX_DAY) {
27906  /* Convert day from one-based to zero-based (internal). This may
27907  * cause the day part to be negative, which is OK.
27908  */
27909  d -= 1.0;
27910  }
27911  } else {
27912  /* All components default to 0 except day-of-month which defaults
27913  * to 1. However, because our internal day-of-month is zero-based,
27914  * it also defaults to zero here.
27915  */
27916  d = 0.0;
27917  }
27918  dparts[idx] = d;
27919  }
27920 
27921  DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
27922  (double) dparts[0], (double) dparts[1],
27923  (double) dparts[2], (double) dparts[3],
27924  (double) dparts[4], (double) dparts[5],
27925  (double) dparts[6], (double) dparts[7]));
27926 }
27927 
27928 /*
27929  * Indirect magic value lookup for Date methods.
27930  *
27931  * Date methods don't put their control flags into the function magic value
27932  * because they wouldn't fit into a LIGHTFUNC's magic field. Instead, the
27933  * magic value is set to an index pointing to the array of control flags
27934  * below.
27935  *
27936  * This must be kept in strict sync with genbuiltins.py!
27937  */
27938 
27939 static duk_uint16_t duk__date_magics[] = {
27940  /* 0: toString */
27941  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
27942 
27943  /* 1: toDateString */
27944  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
27945 
27946  /* 2: toTimeString */
27947  DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
27948 
27949  /* 3: toLocaleString */
27950  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
27951 
27952  /* 4: toLocaleDateString */
27953  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
27954 
27955  /* 5: toLocaleTimeString */
27956  DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
27957 
27958  /* 6: toUTCString */
27959  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
27960 
27961  /* 7: toISOString */
27962  DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
27963 
27964  /* 8: getFullYear */
27965  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
27966 
27967  /* 9: getUTCFullYear */
27968  0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
27969 
27970  /* 10: getMonth */
27971  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
27972 
27973  /* 11: getUTCMonth */
27974  0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
27975 
27976  /* 12: getDate */
27977  DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
27978 
27979  /* 13: getUTCDate */
27980  DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
27981 
27982  /* 14: getDay */
27983  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
27984 
27985  /* 15: getUTCDay */
27986  0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
27987 
27988  /* 16: getHours */
27989  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
27990 
27991  /* 17: getUTCHours */
27992  0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
27993 
27994  /* 18: getMinutes */
27995  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
27996 
27997  /* 19: getUTCMinutes */
27998  0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
27999 
28000  /* 20: getSeconds */
28001  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
28002 
28003  /* 21: getUTCSeconds */
28004  0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
28005 
28006  /* 22: getMilliseconds */
28007  DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
28008 
28009  /* 23: getUTCMilliseconds */
28010  0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
28011 
28012  /* 24: setMilliseconds */
28013  DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
28014 
28015  /* 25: setUTCMilliseconds */
28016  DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
28017 
28018  /* 26: setSeconds */
28019  DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
28020 
28021  /* 27: setUTCSeconds */
28022  DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
28023 
28024  /* 28: setMinutes */
28025  DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
28026 
28027  /* 29: setUTCMinutes */
28028  DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
28029 
28030  /* 30: setHours */
28031  DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
28032 
28033  /* 31: setUTCHours */
28034  DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
28035 
28036  /* 32: setDate */
28037  DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
28038 
28039  /* 33: setUTCDate */
28040  0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
28041 
28042  /* 34: setMonth */
28043  DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
28044 
28045  /* 35: setUTCMonth */
28046  0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
28047 
28048  /* 36: setFullYear */
28049  DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
28050 
28051  /* 37: setUTCFullYear */
28052  DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
28053 
28054  /* 38: getYear */
28055  DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
28056 
28057  /* 39: setYear */
28058  DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
28059 };
28060 
28061 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_context *ctx) {
28062  duk_small_int_t magicidx = (duk_small_uint_t) duk_get_current_magic(ctx);
28063  DUK_ASSERT(magicidx >= 0 && magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
28064  return (duk_small_uint_t) duk__date_magics[magicidx];
28065 }
28066 
28067 #if defined(DUK_USE_DATE_BUILTIN)
28068 /*
28069  * Constructor calls
28070  */
28071 
28072 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_context *ctx) {
28073  duk_idx_t nargs = duk_get_top(ctx);
28074  duk_bool_t is_cons = duk_is_constructor_call(ctx);
28075  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
28076  duk_double_t d;
28077 
28078  DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
28079 
28080  (void) duk_push_object_helper(ctx,
28081  DUK_HOBJECT_FLAG_EXTENSIBLE |
28082  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
28083  DUK_BIDX_DATE_PROTOTYPE);
28084 
28085  /* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
28086  * is mutable.
28087  */
28088 
28089  if (nargs == 0 || !is_cons) {
28090  d = duk__timeclip(DUK_USE_DATE_GET_NOW(ctx));
28091  duk_push_number(ctx, d);
28092  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
28093  if (!is_cons) {
28094  /* called as a normal function: return new Date().toString() */
28095  duk_to_string(ctx, -1);
28096  }
28097  return 1;
28098  } else if (nargs == 1) {
28099  const char *str;
28100  duk_to_primitive(ctx, 0, DUK_HINT_NONE);
28101  str = duk_get_string_notsymbol(ctx, 0);
28102  if (str) {
28103  duk__parse_string(ctx, str);
28104  duk_replace(ctx, 0); /* may be NaN */
28105  }
28106  d = duk__timeclip(duk_to_number(ctx, 0)); /* symbols fail here */
28107  duk_push_number(ctx, d);
28108  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
28109  return 1;
28110  }
28111 
28112  duk__set_parts_from_args(ctx, dparts, nargs);
28113 
28114  /* Parts are in local time, convert when setting. */
28115 
28116  (void) duk__set_this_timeval_from_dparts(ctx, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/); /* -> [ ... this timeval ] */
28117  duk_pop(ctx); /* -> [ ... this ] */
28118  return 1;
28119 }
28120 
28121 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx) {
28122  return duk__parse_string(ctx, duk_to_string(ctx, 0));
28123 }
28124 
28125 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx) {
28126  duk_idx_t nargs = duk_get_top(ctx);
28127  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
28128  duk_double_t d;
28129 
28130  /* Behavior for nargs < 2 is implementation dependent: currently we'll
28131  * set a NaN time value (matching V8 behavior) in this case.
28132  */
28133 
28134  if (nargs < 2) {
28135  duk_push_nan(ctx);
28136  } else {
28137  duk__set_parts_from_args(ctx, dparts, nargs);
28138  d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
28139  duk_push_number(ctx, d);
28140  }
28141  return 1;
28142 }
28143 
28144 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx) {
28145  duk_double_t d;
28146 
28147  d = DUK_USE_DATE_GET_NOW(ctx);
28148  DUK_ASSERT(duk__timeclip(d) == d); /* TimeClip() should never be necessary */
28149  duk_push_number(ctx, d);
28150  return 1;
28151 }
28152 
28153 /*
28154  * String/JSON conversions
28155  *
28156  * Human readable conversions are now basically ISO 8601 with a space
28157  * (instead of 'T') as the date/time separator. This is a good baseline
28158  * and is platform independent.
28159  *
28160  * A shared native helper to provide many conversions. Magic value contains
28161  * a set of flags. The helper provides:
28162  *
28163  * toString()
28164  * toDateString()
28165  * toTimeString()
28166  * toLocaleString()
28167  * toLocaleDateString()
28168  * toLocaleTimeString()
28169  * toUTCString()
28170  * toISOString()
28171  *
28172  * Notes:
28173  *
28174  * - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
28175  * required to be the same Ecmascript function object (!), so it is
28176  * omitted from here.
28177  *
28178  * - Date.prototype.toUTCString(): E5.1 specification does not require a
28179  * specific format, but result should be human readable. The
28180  * specification suggests using ISO 8601 format with a space (instead
28181  * of 'T') separator if a more human readable format is not available.
28182  *
28183  * - Date.prototype.toISOString(): unlike other conversion functions,
28184  * toISOString() requires a RangeError for invalid date values.
28185  */
28186 
28187 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx) {
28188  duk_small_uint_t flags = duk__date_get_indirect_magic(ctx);
28189  return duk__to_string_helper(ctx, flags);
28190 }
28191 
28192 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx) {
28193  /* This native function is also used for Date.prototype.getTime()
28194  * as their behavior is identical.
28195  */
28196 
28197  duk_double_t d = duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ this ] */
28198  DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
28199  duk_push_number(ctx, d);
28200  return 1;
28201 }
28202 
28203 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx) {
28204  /* Note: toJSON() is a generic function which works even if 'this'
28205  * is not a Date. The sole argument is ignored.
28206  */
28207 
28208  duk_push_this(ctx);
28209  duk_to_object(ctx, -1);
28210 
28211  duk_dup_top(ctx);
28212  duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
28213  if (duk_is_number(ctx, -1)) {
28214  duk_double_t d = duk_get_number(ctx, -1);
28215  if (!DUK_ISFINITE(d)) {
28216  duk_push_null(ctx);
28217  return 1;
28218  }
28219  }
28220  duk_pop(ctx);
28221 
28222  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_TO_ISO_STRING);
28223  duk_dup_m2(ctx); /* -> [ O toIsoString O ] */
28224  duk_call_method(ctx, 0);
28225  return 1;
28226 }
28227 
28228 /*
28229  * Getters.
28230  *
28231  * Implementing getters is quite easy. The internal time value is either
28232  * NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
28233  * The internal time value can be converted to integer parts, and each
28234  * part will be normalized and will fit into a 32-bit signed integer.
28235  *
28236  * A shared native helper to provide all getters. Magic value contains
28237  * a set of flags and also packs the date component index argument. The
28238  * helper provides:
28239  *
28240  * getFullYear()
28241  * getUTCFullYear()
28242  * getMonth()
28243  * getUTCMonth()
28244  * getDate()
28245  * getUTCDate()
28246  * getDay()
28247  * getUTCDay()
28248  * getHours()
28249  * getUTCHours()
28250  * getMinutes()
28251  * getUTCMinutes()
28252  * getSeconds()
28253  * getUTCSeconds()
28254  * getMilliseconds()
28255  * getUTCMilliseconds()
28256  * getYear()
28257  *
28258  * Notes:
28259  *
28260  * - Date.prototype.getDate(): 'date' means day-of-month, and is
28261  * zero-based in internal calculations but public API expects it to
28262  * be one-based.
28263  *
28264  * - Date.prototype.getTime() and Date.prototype.valueOf() have identical
28265  * behavior. They have separate function objects, but share the same C
28266  * function (duk_bi_date_prototype_value_of).
28267  */
28268 
28269 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx) {
28270  duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(ctx);
28271  return duk__get_part_helper(ctx, flags_and_idx);
28272 }
28273 
28274 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx) {
28275  /*
28276  * Return (t - LocalTime(t)) in minutes:
28277  *
28278  * t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
28279  * = -(LocalTZA + DaylightSavingTA(t))
28280  *
28281  * where DaylightSavingTA() is checked for time 't'.
28282  *
28283  * Note that the sign of the result is opposite to common usage,
28284  * e.g. for EE(S)T which normally is +2h or +3h from UTC, this
28285  * function returns -120 or -180.
28286  *
28287  */
28288 
28289  duk_double_t d;
28290  duk_int_t tzoffset;
28291 
28292  /* Note: DST adjustment is determined using UTC time. */
28293  d = duk__push_this_get_timeval(ctx, 0 /*flags*/);
28294  DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
28295  if (DUK_ISNAN(d)) {
28296  duk_push_nan(ctx);
28297  } else {
28298  DUK_ASSERT(DUK_ISFINITE(d));
28299  tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
28300  duk_push_int(ctx, -tzoffset / 60);
28301  }
28302  return 1;
28303 }
28304 
28305 /*
28306  * Setters.
28307  *
28308  * Setters are a bit more complicated than getters. Component setters
28309  * break down the current time value into its (normalized) component
28310  * parts, replace one or more components with -unnormalized- new values,
28311  * and the components are then converted back into a time value. As an
28312  * example of using unnormalized values:
28313  *
28314  * var d = new Date(1234567890);
28315  *
28316  * is equivalent to:
28317  *
28318  * var d = new Date(0);
28319  * d.setUTCMilliseconds(1234567890);
28320  *
28321  * A shared native helper to provide almost all setters. Magic value
28322  * contains a set of flags and also packs the "maxnargs" argument. The
28323  * helper provides:
28324  *
28325  * setMilliseconds()
28326  * setUTCMilliseconds()
28327  * setSeconds()
28328  * setUTCSeconds()
28329  * setMinutes()
28330  * setUTCMinutes()
28331  * setHours()
28332  * setUTCHours()
28333  * setDate()
28334  * setUTCDate()
28335  * setMonth()
28336  * setUTCMonth()
28337  * setFullYear()
28338  * setUTCFullYear()
28339  * setYear()
28340  *
28341  * Notes:
28342  *
28343  * - Date.prototype.setYear() (Section B addition): special year check
28344  * is omitted. NaN / Infinity will just flow through and ultimately
28345  * result in a NaN internal time value.
28346  *
28347  * - Date.prototype.setYear() does not have optional arguments for
28348  * setting month and day-in-month (like setFullYear()), but we indicate
28349  * 'maxnargs' to be 3 to get the year written to the correct component
28350  * index in duk__set_part_helper(). The function has nargs == 1, so only
28351  * the year will be set regardless of actual argument count.
28352  */
28353 
28354 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx) {
28355  duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(ctx);
28356  return duk__set_part_helper(ctx, flags_and_maxnargs);
28357 }
28358 
28359 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx) {
28360  duk_double_t d;
28361 
28362  (void) duk__push_this_get_timeval(ctx, 0 /*flags*/); /* -> [ timeval this ] */
28363  d = duk__timeclip(duk_to_number(ctx, 0));
28364  duk_push_number(ctx, d);
28365  duk_dup_top(ctx);
28366  duk_put_prop_stridx_short(ctx, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
28367 
28368  return 1;
28369 }
28370 
28371 #endif /* DUK_USE_DATE_BUILTIN */
28372 
28373 /* automatic undefs */
28374 #undef DUK__CF_ACCEPT
28375 #undef DUK__CF_ACCEPT_NUL
28376 #undef DUK__CF_NEG
28377 #undef DUK__DPRINT_DPARTS
28378 #undef DUK__DPRINT_PARTS
28379 #undef DUK__DPRINT_PARTS_AND_DPARTS
28380 #undef DUK__LOCAL_TZOFFSET_MAXITER
28381 #undef DUK__NUM_ISO8601_PARSER_PARTS
28382 #undef DUK__PACK_RULE
28383 #undef DUK__PI_DAY
28384 #undef DUK__PI_HOUR
28385 #undef DUK__PI_MILLISECOND
28386 #undef DUK__PI_MINUTE
28387 #undef DUK__PI_MONTH
28388 #undef DUK__PI_SECOND
28389 #undef DUK__PI_TZHOUR
28390 #undef DUK__PI_TZMINUTE
28391 #undef DUK__PI_YEAR
28392 #undef DUK__PM_DAY
28393 #undef DUK__PM_HOUR
28394 #undef DUK__PM_MILLISECOND
28395 #undef DUK__PM_MINUTE
28396 #undef DUK__PM_MONTH
28397 #undef DUK__PM_SECOND
28398 #undef DUK__PM_TZHOUR
28399 #undef DUK__PM_TZMINUTE
28400 #undef DUK__PM_YEAR
28401 #undef DUK__RULE_MASK_PART_SEP
28402 #undef DUK__SI_COLON
28403 #undef DUK__SI_MINUS
28404 #undef DUK__SI_NUL
28405 #undef DUK__SI_PERIOD
28406 #undef DUK__SI_PLUS
28407 #undef DUK__SI_SPACE
28408 #undef DUK__SI_T
28409 #undef DUK__SI_Z
28410 #undef DUK__SM_COLON
28411 #undef DUK__SM_MINUS
28412 #undef DUK__SM_NUL
28413 #undef DUK__SM_PERIOD
28414 #undef DUK__SM_PLUS
28415 #undef DUK__SM_SPACE
28416 #undef DUK__SM_T
28417 #undef DUK__SM_Z
28418 #undef DUK__UNPACK_RULE
28419 #undef DUK__WEEKDAY_MOD_ADDER
28420 #undef DUK__YEAR
28421 /*
28422  * Unix-like Date providers
28423  *
28424  * Generally useful Unix / POSIX / ANSI Date providers.
28425  */
28426 
28427 /* #include duk_internal.h -> already included */
28428 
28429 /* The necessary #includes are in place in duk_config.h. */
28430 
28431 /* Buffer sizes for some UNIX calls. Larger than strictly necessary
28432  * to avoid Valgrind errors.
28433  */
28434 #define DUK__STRPTIME_BUF_SIZE 64
28435 #define DUK__STRFTIME_BUF_SIZE 64
28436 
28437 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
28438 /* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */
28439 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(duk_context *ctx) {
28440  duk_hthread *thr = (duk_hthread *) ctx;
28441  struct timeval tv;
28442  duk_double_t d;
28443 
28444  if (gettimeofday(&tv, NULL) != 0) {
28445  DUK_ERROR_INTERNAL(thr);
28446  }
28447 
28448  d = ((duk_double_t) tv.tv_sec) * 1000.0 +
28449  ((duk_double_t) (tv.tv_usec / 1000));
28450  DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions */
28451 
28452  return d;
28453 }
28454 #endif /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
28455 
28456 #if defined(DUK_USE_DATE_NOW_TIME)
28457 /* Not a very good provider: only full seconds are available. */
28458 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(duk_context *ctx) {
28459  time_t t;
28460 
28461  DUK_UNREF(ctx);
28462  t = time(NULL);
28463  return ((duk_double_t) t) * 1000.0;
28464 }
28465 #endif /* DUK_USE_DATE_NOW_TIME */
28466 
28467 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
28468 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
28469 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
28470  time_t t, t1, t2;
28471  duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
28472  duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
28473  struct tm tms[2];
28474 #if defined(DUK_USE_DATE_TZO_GMTIME)
28475  struct tm *tm_ptr;
28476 #endif
28477 
28478  /* For NaN/inf, the return value doesn't matter. */
28479  if (!DUK_ISFINITE(d)) {
28480  return 0;
28481  }
28482 
28483  /* If not within Ecmascript range, some integer time calculations
28484  * won't work correctly (and some asserts will fail), so bail out
28485  * if so. This fixes test-bug-date-insane-setyear.js. There is
28486  * a +/- 24h leeway in this range check to avoid a test262 corner
28487  * case documented in test-bug-date-timeval-edges.js.
28488  */
28489  if (!duk_bi_date_timeval_in_leeway_range(d)) {
28490  DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
28491  return 0;
28492  }
28493 
28494  /*
28495  * This is a bit tricky to implement portably. The result depends
28496  * on the timestamp (specifically, DST depends on the timestamp).
28497  * If e.g. UNIX APIs are used, they'll have portability issues with
28498  * very small and very large years.
28499  *
28500  * Current approach:
28501  *
28502  * - Stay within portable UNIX limits by using equivalent year mapping.
28503  * Avoid year 1970 and 2038 as some conversions start to fail, at
28504  * least on some platforms. Avoiding 1970 means that there are
28505  * currently DST discrepancies for 1970.
28506  *
28507  * - Create a UTC and local time breakdowns from 't'. Then create
28508  * a time_t using gmtime() and localtime() and compute the time
28509  * difference between the two.
28510  *
28511  * Equivalent year mapping (E5 Section 15.9.1.8):
28512  *
28513  * If the host environment provides functionality for determining
28514  * daylight saving time, the implementation of ECMAScript is free
28515  * to map the year in question to an equivalent year (same
28516  * leap-year-ness and same starting week day for the year) for which
28517  * the host environment provides daylight saving time information.
28518  * The only restriction is that all equivalent years should produce
28519  * the same result.
28520  *
28521  * This approach is quite reasonable but not entirely correct, e.g.
28522  * the specification also states (E5 Section 15.9.1.8):
28523  *
28524  * The implementation of ECMAScript should not try to determine
28525  * whether the exact time was subject to daylight saving time, but
28526  * just whether daylight saving time would have been in effect if
28527  * the _current daylight saving time algorithm_ had been used at the
28528  * time. This avoids complications such as taking into account the
28529  * years that the locale observed daylight saving time year round.
28530  *
28531  * Since we rely on the platform APIs for conversions between local
28532  * time and UTC, we can't guarantee the above. Rather, if the platform
28533  * has historical DST rules they will be applied. This seems to be the
28534  * general preferred direction in Ecmascript standardization (or at least
28535  * implementations) anyway, and even the equivalent year mapping should
28536  * be disabled if the platform is known to handle DST properly for the
28537  * full Ecmascript range.
28538  *
28539  * The following has useful discussion and links:
28540  *
28541  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
28542  */
28543 
28544  duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
28545  DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
28546 
28547  d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
28548  DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
28549  t = (time_t) (d / 1000.0);
28550  DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
28551 
28552  DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
28553 
28554 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
28555  (void) gmtime_r(&t, &tms[0]);
28556  (void) localtime_r(&t, &tms[1]);
28557 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
28558  (void) gmtime_s(&t, &tms[0]);
28559  (void) localtime_s(&t, &tms[1]);
28560 #elif defined(DUK_USE_DATE_TZO_GMTIME)
28561  tm_ptr = gmtime(&t);
28562  DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
28563  tm_ptr = localtime(&t);
28564  DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
28565 #else
28566 #error internal error
28567 #endif
28568  DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
28569  "wday:%ld,yday:%ld,isdst:%ld}",
28570  (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
28571  (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
28572  (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
28573  DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
28574  "wday:%ld,yday:%ld,isdst:%ld}",
28575  (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
28576  (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
28577  (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
28578 
28579  /* tm_isdst is both an input and an output to mktime(), use 0 to
28580  * avoid DST handling in mktime():
28581  * - https://github.com/svaarala/duktape/issues/406
28582  * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
28583  */
28584  tms[0].tm_isdst = 0;
28585  tms[1].tm_isdst = 0;
28586  t1 = mktime(&tms[0]); /* UTC */
28587  t2 = mktime(&tms[1]); /* local */
28588  if (t1 == (time_t) -1 || t2 == (time_t) -1) {
28589  /* This check used to be for (t < 0) but on some platforms
28590  * time_t is unsigned and apparently the proper way to detect
28591  * an mktime() error return is the cast above. See e.g.:
28592  * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
28593  */
28594  goto error;
28595  }
28596  DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
28597 
28598  /* Compute final offset in seconds, positive if local time ahead of
28599  * UTC (returned value is UTC-to-local offset).
28600  *
28601  * difftime() returns a double, so coercion to int generates quite
28602  * a lot of code. Direct subtraction is not portable, however.
28603  * XXX: allow direct subtraction on known platforms.
28604  */
28605 #if 0
28606  return (duk_int_t) (t2 - t1);
28607 #endif
28608  return (duk_int_t) difftime(t2, t1);
28609 
28610  error:
28611  /* XXX: return something more useful, so that caller can throw? */
28612  DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
28613  return 0;
28614 }
28615 #endif /* DUK_USE_DATE_TZO_GMTIME */
28616 
28617 #if defined(DUK_USE_DATE_PRS_STRPTIME)
28618 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_context *ctx, const char *str) {
28619  struct tm tm;
28620  time_t t;
28621  char buf[DUK__STRPTIME_BUF_SIZE];
28622 
28623  /* copy to buffer with spare to avoid Valgrind gripes from strptime */
28624  DUK_ASSERT(str != NULL);
28625  DUK_MEMZERO(buf, sizeof(buf)); /* valgrind whine without this */
28626  DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
28627  buf[sizeof(buf) - 1] = (char) 0;
28628 
28629  DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
28630 
28631  DUK_MEMZERO(&tm, sizeof(tm));
28632  if (strptime((const char *) buf, "%c", &tm) != NULL) {
28633  DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
28634  "wday:%ld,yday:%ld,isdst:%ld}",
28635  (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
28636  (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
28637  (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
28638  tm.tm_isdst = -1; /* negative: dst info not available */
28639 
28640  t = mktime(&tm);
28641  DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
28642  if (t >= 0) {
28643  duk_push_number(ctx, ((duk_double_t) t) * 1000.0);
28644  return 1;
28645  }
28646  }
28647 
28648  return 0;
28649 }
28650 #endif /* DUK_USE_DATE_PRS_STRPTIME */
28651 
28652 #if defined(DUK_USE_DATE_PRS_GETDATE)
28653 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_context *ctx, const char *str) {
28654  struct tm tm;
28655  duk_small_int_t rc;
28656  time_t t;
28657 
28658  /* For this to work, DATEMSK must be set, so this is not very
28659  * convenient for an embeddable interpreter.
28660  */
28661 
28662  DUK_MEMZERO(&tm, sizeof(struct tm));
28663  rc = (duk_small_int_t) getdate_r(str, &tm);
28664  DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
28665 
28666  if (rc == 0) {
28667  t = mktime(&tm);
28668  DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
28669  if (t >= 0) {
28670  duk_push_number(ctx, (duk_double_t) t);
28671  return 1;
28672  }
28673  }
28674 
28675  return 0;
28676 }
28677 #endif /* DUK_USE_DATE_PRS_GETDATE */
28678 
28679 #if defined(DUK_USE_DATE_FMT_STRFTIME)
28680 DUK_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) {
28681  char buf[DUK__STRFTIME_BUF_SIZE];
28682  struct tm tm;
28683  const char *fmt;
28684 
28685  DUK_UNREF(tzoffset);
28686 
28687  /* If the platform doesn't support the entire Ecmascript range, we need
28688  * to return 0 so that the caller can fall back to the default formatter.
28689  *
28690  * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript
28691  * range is supported. For smaller time_t values (4 bytes in practice),
28692  * assumes that the signed 32-bit range is supported.
28693  *
28694  * XXX: detect this more correctly per platform. The size of time_t is
28695  * probably not an accurate guarantee of strftime() supporting or not
28696  * supporting a large time range (the full Ecmascript range).
28697  */
28698  if (sizeof(time_t) < 8 &&
28699  (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
28700  /* be paranoid for 32-bit time values (even avoiding negative ones) */
28701  return 0;
28702  }
28703 
28704  DUK_MEMZERO(&tm, sizeof(tm));
28705  tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
28706  tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
28707  tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
28708  tm.tm_mday = parts[DUK_DATE_IDX_DAY]; /* already one-based */
28709  tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1; /* one-based -> zero-based */
28710  tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
28711  tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
28712  tm.tm_isdst = 0;
28713 
28714  DUK_MEMZERO(buf, sizeof(buf));
28715  if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
28716  fmt = "%c";
28717  } else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
28718  fmt = "%x";
28719  } else {
28720  DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
28721  fmt = "%X";
28722  }
28723  (void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
28724  DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
28725 
28726  duk_push_string(ctx, buf);
28727  return 1;
28728 }
28729 #endif /* DUK_USE_DATE_FMT_STRFTIME */
28730 
28731 /* automatic undefs */
28732 #undef DUK__STRFTIME_BUF_SIZE
28733 #undef DUK__STRPTIME_BUF_SIZE
28734 /*
28735  * Windows Date providers
28736  *
28737  * Platform specific links:
28738  *
28739  * - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
28740  */
28741 
28742 /* #include duk_internal.h -> already included */
28743 
28744 /* The necessary #includes are in place in duk_config.h. */
28745 
28746 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
28747 /* Shared Windows helpers. */
28748 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
28749  FILETIME ft;
28750  if (SystemTimeToFileTime(st, &ft) == 0) {
28751  DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
28752  res->QuadPart = 0;
28753  } else {
28754  res->LowPart = ft.dwLowDateTime;
28755  res->HighPart = ft.dwHighDateTime;
28756  }
28757 }
28758 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
28759  DUK_MEMZERO((void *) st, sizeof(*st));
28760  st->wYear = 1970;
28761  st->wMonth = 1;
28762  st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
28763  st->wDay = 1;
28764  DUK_ASSERT(st->wHour == 0);
28765  DUK_ASSERT(st->wMinute == 0);
28766  DUK_ASSERT(st->wSecond == 0);
28767  DUK_ASSERT(st->wMilliseconds == 0);
28768 }
28769 #endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
28770 
28771 #if defined(DUK_USE_DATE_NOW_WINDOWS)
28772 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
28773  /* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
28774  * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
28775  */
28776  SYSTEMTIME st1, st2;
28777  ULARGE_INTEGER tmp1, tmp2;
28778 
28779  DUK_UNREF(ctx);
28780 
28781  GetSystemTime(&st1);
28782  duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
28783 
28784  duk__set_systime_jan1970(&st2);
28785  duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
28786 
28787  /* Difference is in 100ns units, convert to milliseconds w/o fractions */
28788  return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
28789 }
28790 #endif /* DUK_USE_DATE_NOW_WINDOWS */
28791 
28792 
28793 #if defined(DUK_USE_DATE_TZO_WINDOWS)
28794 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
28795  SYSTEMTIME st1;
28796  SYSTEMTIME st2;
28797  SYSTEMTIME st3;
28798  ULARGE_INTEGER tmp1;
28799  ULARGE_INTEGER tmp2;
28800  ULARGE_INTEGER tmp3;
28801  FILETIME ft1;
28802 
28803  /* XXX: handling of timestamps outside Windows supported range.
28804  * How does Windows deal with dates before 1600? Does windows
28805  * support all Ecmascript years (like -200000 and +200000)?
28806  * Should equivalent year mapping be used here too? If so, use
28807  * a shared helper (currently integrated into timeval-to-parts).
28808  */
28809 
28810  /* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
28811  * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
28812  */
28813 
28814  duk__set_systime_jan1970(&st1);
28815  duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
28816  tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
28817  tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
28818 
28819  ft1.dwLowDateTime = tmp2.LowPart;
28820  ft1.dwHighDateTime = tmp2.HighPart;
28821  FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
28822  if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
28823  DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
28824  return 0;
28825  }
28826  duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
28827 
28828  /* Positive if local time ahead of UTC. */
28829  return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */
28830 }
28831 #endif /* DUK_USE_DATE_TZO_WINDOWS */
28832 /*
28833  * Duktape built-ins
28834  *
28835  * Size optimization note: it might seem that vararg multipurpose functions
28836  * like fin(), enc(), and dec() are not very size optimal, but using a single
28837  * user-visible Ecmascript function saves a lot of run-time footprint; each
28838  * Function instance takes >100 bytes. Using a shared native helper and a
28839  * 'magic' value won't save much if there are multiple Function instances
28840  * anyway.
28841  */
28842 
28843 /* #include duk_internal.h -> already included */
28844 
28845 #if defined(DUK_USE_DUKTAPE_BUILTIN)
28846 
28847 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx) {
28848  duk_inspect_value(ctx, -1);
28849  return 1;
28850 }
28851 
28852 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx) {
28853  duk_int_t level;
28854 
28855  level = duk_to_int(ctx, 0);
28856  duk_inspect_callstack_entry(ctx, level);
28857  return 1;
28858 }
28859 
28860 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx) {
28861  duk_hthread *thr = (duk_hthread *) ctx;
28862  duk_small_uint_t flags;
28863  duk_bool_t rc;
28864 
28865  flags = (duk_small_uint_t) duk_get_uint(ctx, 0);
28866  rc = duk_heap_mark_and_sweep(thr->heap, flags);
28867 
28868  /* XXX: Not sure what the best return value would be in the API.
28869  * Return a boolean for now. Note that rc == 0 is success (true).
28870  */
28871  duk_push_boolean(ctx, !rc);
28872  return 1;
28873 }
28874 
28875 #if defined(DUK_USE_FINALIZER_SUPPORT)
28876 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx) {
28877  (void) duk_require_hobject(ctx, 0);
28878  if (duk_get_top(ctx) >= 2) {
28879  /* Set: currently a finalizer is disabled by setting it to
28880  * undefined; this does not remove the property at the moment.
28881  * The value could be type checked to be either a function
28882  * or something else; if something else, the property could
28883  * be deleted.
28884  */
28885  duk_set_top(ctx, 2);
28886  (void) duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_INT_FINALIZER);
28887  return 0;
28888  } else {
28889  /* Get. */
28890  DUK_ASSERT(duk_get_top(ctx) == 1);
28891  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_INT_FINALIZER);
28892  return 1;
28893  }
28894 }
28895 #endif /* DUK_USE_FINALIZER_SUPPORT */
28896 
28897 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx) {
28898  duk_hthread *thr = (duk_hthread *) ctx;
28899  duk_hstring *h_str;
28900 
28901  DUK_UNREF(thr);
28902 
28903  /* Vararg function: must be careful to check/require arguments.
28904  * The JSON helpers accept invalid indices and treat them like
28905  * non-existent optional parameters.
28906  */
28907 
28908  h_str = duk_require_hstring(ctx, 0); /* Could reject symbols, but no point: won't match comparisons. */
28909  duk_require_valid_index(ctx, 1);
28910 
28911  if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
28912  duk_set_top(ctx, 2);
28913  duk_hex_encode(ctx, 1);
28914  DUK_ASSERT_TOP(ctx, 2);
28915  } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
28916  duk_set_top(ctx, 2);
28917  duk_base64_encode(ctx, 1);
28918  DUK_ASSERT_TOP(ctx, 2);
28919 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
28920  } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
28921  duk_bi_json_stringify_helper(ctx,
28922  1 /*idx_value*/,
28923  2 /*idx_replacer*/,
28924  3 /*idx_space*/,
28925  DUK_JSON_FLAG_EXT_CUSTOM |
28926  DUK_JSON_FLAG_ASCII_ONLY |
28927  DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
28928 #endif
28929 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
28930  } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
28931  duk_bi_json_stringify_helper(ctx,
28932  1 /*idx_value*/,
28933  2 /*idx_replacer*/,
28934  3 /*idx_space*/,
28935  DUK_JSON_FLAG_EXT_COMPATIBLE |
28936  DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
28937 #endif
28938  } else {
28939  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28940  }
28941  return 1;
28942 }
28943 
28944 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx) {
28945  duk_hthread *thr = (duk_hthread *) ctx;
28946  duk_hstring *h_str;
28947 
28948  DUK_UNREF(thr);
28949 
28950  /* Vararg function: must be careful to check/require arguments.
28951  * The JSON helpers accept invalid indices and treat them like
28952  * non-existent optional parameters.
28953  */
28954 
28955  h_str = duk_require_hstring(ctx, 0); /* Could reject symbols, but no point: won't match comparisons */
28956  duk_require_valid_index(ctx, 1);
28957 
28958  if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
28959  duk_set_top(ctx, 2);
28960  duk_hex_decode(ctx, 1);
28961  DUK_ASSERT_TOP(ctx, 2);
28962  } else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
28963  duk_set_top(ctx, 2);
28964  duk_base64_decode(ctx, 1);
28965  DUK_ASSERT_TOP(ctx, 2);
28966 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
28967  } else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
28968  duk_bi_json_parse_helper(ctx,
28969  1 /*idx_value*/,
28970  2 /*idx_replacer*/,
28971  DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
28972 #endif
28973 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
28974  } else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
28975  duk_bi_json_parse_helper(ctx,
28976  1 /*idx_value*/,
28977  2 /*idx_replacer*/,
28978  DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
28979 #endif
28980  } else {
28981  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28982  }
28983  return 1;
28984 }
28985 
28986 /*
28987  * Compact an object
28988  */
28989 
28990 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx) {
28991  DUK_ASSERT_TOP(ctx, 1);
28992  duk_compact(ctx, 0);
28993  return 1; /* return the argument object */
28994 }
28995 
28996 #endif /* DUK_USE_DUKTAPE_BUILTIN */
28997 /*
28998  * WHATWG Encoding API built-ins
28999  *
29000  * API specification: https://encoding.spec.whatwg.org/#api
29001  * Web IDL: https://www.w3.org/TR/WebIDL/
29002  */
29003 
29004 /* #include duk_internal.h -> already included */
29005 
29006 /*
29007  * Data structures for encoding/decoding
29008  */
29009 
29010 typedef struct {
29011  duk_uint8_t *out; /* where to write next byte(s) */
29012  duk_codepoint_t lead; /* lead surrogate */
29014 
29015 typedef struct {
29016  /* UTF-8 decoding state */
29017  duk_codepoint_t codepoint; /* built up incrementally */
29018  duk_uint8_t upper; /* max value of next byte (decode error otherwise) */
29019  duk_uint8_t lower; /* min value of next byte (ditto) */
29020  duk_uint8_t needed; /* how many more bytes we need */
29021  duk_uint8_t bom_handled; /* BOM seen or no longer expected */
29022 
29023  /* Decoder configuration */
29024  duk_uint8_t fatal;
29025  duk_uint8_t ignore_bom;
29027 
29028 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
29029  * (>= 0) or various other states using negative values.
29030  */
29031 #define DUK__CP_CONTINUE (-1) /* continue to next byte, no completed codepoint */
29032 #define DUK__CP_ERROR (-2) /* decoding error */
29033 #define DUK__CP_RETRY (-3) /* decoding error; retry last byte */
29034 
29035 /*
29036  * Raw helpers for encoding/decoding
29037  */
29038 
29039 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
29040 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
29041  *ptr++ = 0xef;
29042  *ptr++ = 0xbf;
29043  *ptr++ = 0xbd;
29044  return ptr;
29045 }
29046 
29047 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
29048  /* (Re)init the decoding state of 'dec_ctx' but leave decoder
29049  * configuration fields untouched.
29050  */
29051  dec_ctx->codepoint = 0x0000L;
29052  dec_ctx->upper = 0xbf;
29053  dec_ctx->lower = 0x80;
29054  dec_ctx->needed = 0;
29055  dec_ctx->bom_handled = 0;
29056 }
29057 
29058 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
29059  /*
29060  * UTF-8 algorithm based on the Encoding specification:
29061  * https://encoding.spec.whatwg.org/#utf-8-decoder
29062  *
29063  * Two main states: decoding initial byte vs. decoding continuation
29064  * bytes. Shortest length encoding is validated by restricting the
29065  * allowed range of first continuation byte using 'lower' and 'upper'.
29066  */
29067 
29068  if (dec_ctx->needed == 0) {
29069  /* process initial byte */
29070  if (x <= 0x7f) {
29071  /* U+0000-U+007F, 1 byte (ASCII) */
29072  return (duk_codepoint_t) x;
29073  } else if (x >= 0xc2 && x <= 0xdf) {
29074  /* U+0080-U+07FF, 2 bytes */
29075  dec_ctx->needed = 1;
29076  dec_ctx->codepoint = x & 0x1f;
29077  DUK_ASSERT(dec_ctx->lower == 0x80);
29078  DUK_ASSERT(dec_ctx->upper == 0xbf);
29079  return DUK__CP_CONTINUE;
29080  } else if (x >= 0xe0 && x <= 0xef) {
29081  /* U+0800-U+FFFF, 3 bytes */
29082  if (x == 0xe0) {
29083  dec_ctx->lower = 0xa0;
29084  DUK_ASSERT(dec_ctx->upper == 0xbf);
29085  } else if (x == 0xed) {
29086  DUK_ASSERT(dec_ctx->lower == 0x80);
29087  dec_ctx->upper = 0x9f;
29088  }
29089  dec_ctx->needed = 2;
29090  dec_ctx->codepoint = x & 0x0f;
29091  return DUK__CP_CONTINUE;
29092  } else if (x >= 0xf0 && x <= 0xf4) {
29093  /* U+010000-U+10FFFF, 4 bytes */
29094  if (x == 0xf0) {
29095  dec_ctx->lower = 0x90;
29096  DUK_ASSERT(dec_ctx->upper == 0xbf);
29097  } else if (x == 0xf4) {
29098  DUK_ASSERT(dec_ctx->lower == 0x80);
29099  dec_ctx->upper = 0x8f;
29100  }
29101  dec_ctx->needed = 3;
29102  dec_ctx->codepoint = x & 0x07;
29103  return DUK__CP_CONTINUE;
29104  } else {
29105  /* not a legal initial byte */
29106  return DUK__CP_ERROR;
29107  }
29108  } else {
29109  /* process continuation byte */
29110  if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
29111  dec_ctx->lower = 0x80;
29112  dec_ctx->upper = 0xbf;
29113  dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
29114  if (--dec_ctx->needed > 0) {
29115  /* need more bytes */
29116  return DUK__CP_CONTINUE;
29117  } else {
29118  /* got a codepoint */
29119  duk_codepoint_t ret;
29120  DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL); /* Decoding rules guarantee. */
29121  ret = dec_ctx->codepoint;
29122  dec_ctx->codepoint = 0x0000L;
29123  dec_ctx->needed = 0;
29124  return ret;
29125  }
29126  } else {
29127  /* We just encountered an illegal UTF-8 continuation byte. This might
29128  * be the initial byte of the next character; if we return a plain
29129  * error status and the decoder is in replacement mode, the character
29130  * will be masked. We still need to alert the caller to the error
29131  * though.
29132  */
29133  dec_ctx->codepoint = 0x0000L;
29134  dec_ctx->needed = 0;
29135  dec_ctx->lower = 0x80;
29136  dec_ctx->upper = 0xbf;
29137  return DUK__CP_RETRY;
29138  }
29139  }
29140 }
29141 
29142 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
29143  duk__encode_context *enc_ctx;
29144 
29145  DUK_ASSERT(codepoint >= 0);
29146  enc_ctx = (duk__encode_context *) udata;
29147  DUK_ASSERT(enc_ctx != NULL);
29148 
29149 #if !defined(DUK_USE_PREFER_SIZE)
29150  if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
29151  /* Fast path for ASCII. */
29152  *enc_ctx->out++ = (duk_uint8_t) codepoint;
29153  return;
29154  }
29155 #endif
29156 
29157  if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
29158  /* cannot legally encode in UTF-8 */
29159  codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
29160  } else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
29161  if (codepoint <= 0xdbffL) {
29162  /* high surrogate */
29163  duk_codepoint_t prev_lead = enc_ctx->lead;
29164  enc_ctx->lead = codepoint;
29165  if (prev_lead == 0x0000L) {
29166  /* high surrogate, no output */
29167  return;
29168  } else {
29169  /* consecutive high surrogates, consider first one unpaired */
29170  codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
29171  }
29172  } else {
29173  /* low surrogate */
29174  if (enc_ctx->lead != 0x0000L) {
29175  codepoint = 0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L);
29176  enc_ctx->lead = 0x0000L;
29177  } else {
29178  /* unpaired low surrogate */
29179  DUK_ASSERT(enc_ctx->lead == 0x0000L);
29180  codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
29181  }
29182  }
29183  } else {
29184  if (enc_ctx->lead != 0x0000L) {
29185  /* unpaired high surrogate: emit replacement character and the input codepoint */
29186  enc_ctx->lead = 0x0000L;
29187  enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
29188  }
29189  }
29190 
29191  /* Codepoint may be original input, a decoded surrogate pair, or may
29192  * have been replaced with U+FFFD.
29193  */
29194  enc_ctx->out += duk_unicode_encode_xutf8(codepoint, enc_ctx->out);
29195 }
29196 
29197 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
29198  * decoder.
29199  */
29200 DUK_LOCAL duk_ret_t duk__decode_helper(duk_context *ctx, duk__decode_context *dec_ctx) {
29201  const duk_uint8_t *input;
29202  duk_size_t len = 0;
29203  duk_size_t len_tmp;
29204  duk_bool_t stream = 0;
29205  duk_codepoint_t codepoint;
29206  duk_uint8_t *output;
29207  const duk_uint8_t *in;
29208  duk_uint8_t *out;
29209 
29210  DUK_ASSERT(dec_ctx != NULL);
29211 
29212  /* Careful with input buffer pointer: any side effects involving
29213  * code execution (e.g. getters, coercion calls, and finalizers)
29214  * may cause a resize and invalidate a pointer we've read. This
29215  * is why the pointer is actually looked up at the last minute.
29216  * Argument validation must still happen first to match WHATWG
29217  * required side effect order.
29218  */
29219 
29220  if (duk_is_undefined(ctx, 0)) {
29221  duk_push_fixed_buffer_nozero(ctx, 0);
29222  duk_replace(ctx, 0);
29223  }
29224  (void) duk_require_buffer_data(ctx, 0, &len); /* Need 'len', avoid pointer. */
29225 
29226  if (duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_UNDEFINED |
29227  DUK_TYPE_MASK_NULL |
29228  DUK_TYPE_MASK_NONE)) {
29229  /* Use defaults, treat missing value like undefined. */
29230  } else {
29231  duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_UNDEFINED |
29232  DUK_TYPE_MASK_NULL |
29233  DUK_TYPE_MASK_LIGHTFUNC |
29234  DUK_TYPE_MASK_BUFFER |
29235  DUK_TYPE_MASK_OBJECT);
29236  if (duk_get_prop_string(ctx, 1, "stream")) {
29237  stream = duk_to_boolean(ctx, -1);
29238  }
29239  }
29240 
29241  /* Allowance is 3*len in the general case because all bytes may potentially
29242  * become U+FFFD. If the first byte completes a non-BMP codepoint it will
29243  * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
29244  * compensate: (1*3)+3 = 6. Non-BMP codepoints are safe otherwise because
29245  * the 4->6 expansion is well under the 3x allowance.
29246  *
29247  * XXX: As with TextEncoder, need a better buffer allocation strategy here.
29248  */
29249  if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
29250  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_RESULT_TOO_LONG);
29251  }
29252  output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, 3 + (3 * len)); /* used parts will be always manually written over */
29253 
29254  input = (const duk_uint8_t *) duk_get_buffer_data(ctx, 0, &len_tmp);
29255  DUK_ASSERT(input != NULL || len == 0);
29256  if (DUK_UNLIKELY(len != len_tmp)) {
29257  /* Very unlikely but possible: source buffer was resized by
29258  * a side effect when fixed buffer was pushed. Output buffer
29259  * may not be large enough to hold output, so just fail if
29260  * length has changed.
29261  */
29262  DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
29263  goto fail_type;
29264  }
29265 
29266  /* From this point onwards it's critical that no side effect occur
29267  * which may disturb 'input': finalizer execution, property accesses,
29268  * active coercions, etc. Even an allocation related mark-and-sweep
29269  * may affect the pointer because it may trigger a pending finalizer.
29270  */
29271 
29272  in = input;
29273  out = output;
29274  while (in < input + len) {
29275  codepoint = duk__utf8_decode_next(dec_ctx, *in++);
29276  if (codepoint < 0) {
29277  if (codepoint == DUK__CP_CONTINUE) {
29278  continue;
29279  }
29280 
29281  /* Decoding error with or without retry. */
29282  DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
29283  if (codepoint == DUK__CP_RETRY) {
29284  --in; /* retry last byte */
29285  }
29286  /* replacement mode: replace with U+FFFD */
29287  codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
29288  if (dec_ctx->fatal) {
29289  /* fatal mode: throw a TypeError */
29290  goto fail_type;
29291  }
29292  /* Continue with 'codepoint', Unicode replacement. */
29293  }
29294  DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
29295 
29296  if (!dec_ctx->bom_handled) {
29297  dec_ctx->bom_handled = 1;
29298  if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
29299  continue;
29300  }
29301  }
29302 
29303  out += duk_unicode_encode_cesu8(codepoint, out);
29304  DUK_ASSERT(out <= output + (3 + (3 * len)));
29305  }
29306 
29307  if (!stream) {
29308  if (dec_ctx->needed != 0) {
29309  /* truncated sequence at end of buffer */
29310  if (dec_ctx->fatal) {
29311  goto fail_type;
29312  } else {
29313  out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
29314  DUK_ASSERT(out <= output + (3 + (3 * len)));
29315  }
29316  }
29317  duk__utf8_decode_init(dec_ctx); /* Initialize decoding state for potential reuse. */
29318  }
29319 
29320  /* Output buffer is fixed and thus stable even if there had been
29321  * side effects (which there shouldn't be).
29322  */
29323  duk_push_lstring(ctx, (const char *) output, (duk_size_t) (out - output));
29324  return 1;
29325 
29326  fail_type:
29327  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_DECODE_FAILED);
29328  DUK_UNREACHABLE();
29329 }
29330 
29331 /*
29332  * Built-in bindings
29333  */
29334 
29335 #if defined(DUK_USE_ENCODING_BUILTINS)
29336 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx) {
29337  /* TextEncoder currently requires no persistent state, so the constructor
29338  * does nothing on purpose.
29339  */
29340 
29341  duk_require_constructor_call(ctx);
29342  return 0;
29343 }
29344 
29345 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx) {
29346  duk_push_string(ctx, "utf-8");
29347  return 1;
29348 }
29349 
29350 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx) {
29351  duk__encode_context enc_ctx;
29352  duk_size_t len;
29353  duk_size_t final_len;
29354  duk_uint8_t *output;
29355 
29356  DUK_ASSERT_TOP(ctx, 1);
29357  if (duk_is_undefined(ctx, 0)) {
29358  len = 0;
29359  final_len = len;
29360  } else {
29361  duk_hstring *h_input;
29362 
29363  h_input = duk_to_hstring(ctx, 0);
29364  DUK_ASSERT(h_input != NULL);
29365 
29366  len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
29367  if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
29368  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_RESULT_TOO_LONG);
29369  }
29370  }
29371 
29372  /* Allowance is 3*len because all bytes can potentially be replaced with
29373  * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
29374  * Rely on dynamic buffer data pointer stability: no other code has
29375  * access to the data pointer.
29376  *
29377  * XXX: The buffer allocation strategy used here is rather inefficient.
29378  * Maybe switch to a chunk-based strategy, or preprocess the string to
29379  * figure out the space needed ahead of time?
29380  */
29381  DUK_ASSERT(3 * len >= len);
29382  output = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, 3 * len);
29383 
29384  if (len > 0) {
29385  DUK_ASSERT(duk_is_string(ctx, 0)); /* True if len > 0. */
29386 
29387  /* XXX: duk_decode_string() is used to process the input
29388  * string. For standard Ecmascript strings, represented
29389  * internally as CESU-8, this is fine. However, behavior
29390  * beyond CESU-8 is not very strict: codepoints using an
29391  * extended form of UTF-8 are also accepted, and invalid
29392  * codepoint sequences (which are allowed in Duktape strings)
29393  * are not handled as well as they could (e.g. invalid
29394  * continuation bytes may mask following codepoints).
29395  * This is how Ecmascript code would also see such strings.
29396  * Maybe replace duk_decode_string() with an explicit strict
29397  * CESU-8 decoder here?
29398  */
29399  enc_ctx.lead = 0x0000L;
29400  enc_ctx.out = output;
29401  duk_decode_string(ctx, 0, duk__utf8_encode_char, (void *) &enc_ctx);
29402  if (enc_ctx.lead != 0x0000L) {
29403  /* unpaired high surrogate at end of string */
29404  enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
29405  DUK_ASSERT(enc_ctx.out <= output + (3 * len));
29406  }
29407 
29408  /* The output buffer is usually very much oversized, so shrink it to
29409  * actually needed size. Pointer stability assumed up to this point.
29410  */
29411  DUK_ASSERT_TOP(ctx, 2);
29412  DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(ctx, -1, NULL));
29413 
29414  final_len = (duk_size_t) (enc_ctx.out - output);
29415  duk_resize_buffer(ctx, -1, final_len);
29416  /* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
29417  }
29418 
29419  /* Standard WHATWG output is a Uint8Array. Here the Uint8Array will
29420  * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
29421  * created as 'new Uint8Array(N)'. Ecmascript code won't see the
29422  * difference but C code will. When bufferobjects are not supported,
29423  * returns a plain dynamic buffer.
29424  */
29425 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29426  duk_push_buffer_object(ctx, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
29427 #endif
29428  return 1;
29429 }
29430 
29431 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx) {
29432  duk__decode_context *dec_ctx;
29433  duk_bool_t fatal = 0;
29434  duk_bool_t ignore_bom = 0;
29435 
29436  DUK_ASSERT_TOP(ctx, 2);
29437  duk_require_constructor_call(ctx);
29438  if (!duk_is_undefined(ctx, 0)) {
29439  /* XXX: For now ignore 'label' (encoding identifier). */
29440  duk_to_string(ctx, 0);
29441  }
29442  if (!duk_is_null_or_undefined(ctx, 1)) {
29443  if (duk_get_prop_string(ctx, 1, "fatal")) {
29444  fatal = duk_to_boolean(ctx, -1);
29445  }
29446  if (duk_get_prop_string(ctx, 1, "ignoreBOM")) {
29447  ignore_bom = duk_to_boolean(ctx, -1);
29448  }
29449  }
29450 
29451  duk_push_this(ctx);
29452 
29453  /* The decode context is not assumed to be zeroed; all fields are
29454  * initialized explicitly.
29455  */
29456  dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(ctx, sizeof(duk__decode_context));
29457  dec_ctx->fatal = fatal;
29458  dec_ctx->ignore_bom = ignore_bom;
29459  duk__utf8_decode_init(dec_ctx); /* Initializes remaining fields. */
29460 
29461  duk_put_prop_string(ctx, -2, "\xff" "Context");
29462  return 0;
29463 }
29464 
29465 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
29466 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_context *ctx) {
29467  duk__decode_context *dec_ctx;
29468  duk_push_this(ctx);
29469  duk_get_prop_string(ctx, -1, "\xff" "Context");
29470  dec_ctx = (duk__decode_context *) duk_require_buffer(ctx, -1, NULL);
29471  DUK_ASSERT(dec_ctx != NULL);
29472  return dec_ctx;
29473 }
29474 
29475 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx) {
29476  duk__decode_context *dec_ctx;
29477  duk_int_t magic;
29478 
29479  dec_ctx = duk__get_textdecoder_context(ctx);
29480  magic = duk_get_current_magic(ctx);
29481  switch (magic) {
29482  case 0:
29483  /* Encoding is now fixed, so _Context lookup is only needed to
29484  * validate the 'this' binding (TypeError if not TextDecoder-like).
29485  */
29486  duk_push_string(ctx, "utf-8");
29487  break;
29488  case 1:
29489  duk_push_boolean(ctx, dec_ctx->fatal);
29490  break;
29491  default:
29492  duk_push_boolean(ctx, dec_ctx->ignore_bom);
29493  break;
29494  }
29495 
29496  return 1;
29497 }
29498 
29499 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx) {
29500  duk__decode_context *dec_ctx;
29501 
29502  dec_ctx = duk__get_textdecoder_context(ctx);
29503  return duk__decode_helper(ctx, dec_ctx);
29504 }
29505 #endif /* DUK_USE_ENCODING_BUILTINS */
29506 
29507 /*
29508  * Internal helper for Node.js Buffer
29509  */
29510 
29511 /* Internal helper used for Node.js Buffer .toString(). Value stack convention
29512  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
29513  * index 0, and decode options (not present for Buffer) at index 1. Return value
29514  * is a Duktape/C function return value.
29515  */
29516 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_context *ctx) {
29517  duk__decode_context dec_ctx;
29518 
29519  dec_ctx.fatal = 0; /* use replacement chars */
29520  dec_ctx.ignore_bom = 1; /* ignore BOMs (matches Node.js Buffer .toString()) */
29521  duk__utf8_decode_init(&dec_ctx);
29522 
29523  return duk__decode_helper(ctx, &dec_ctx);
29524 }
29525 
29526 /* automatic undefs */
29527 #undef DUK__CP_CONTINUE
29528 #undef DUK__CP_ERROR
29529 #undef DUK__CP_RETRY
29530 /*
29531  * Error built-ins
29532  */
29533 
29534 /* #include duk_internal.h -> already included */
29535 
29536 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx) {
29537  /* Behavior for constructor and non-constructor call is
29538  * the same except for augmenting the created error. When
29539  * called as a constructor, the caller (duk_new()) will handle
29540  * augmentation; when called as normal function, we need to do
29541  * it here.
29542  */
29543 
29544  duk_hthread *thr = (duk_hthread *) ctx;
29545  duk_small_int_t bidx_prototype = duk_get_current_magic(ctx);
29546 
29547  /* same for both error and each subclass like TypeError */
29548  duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
29549  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
29550 
29551  DUK_UNREF(thr);
29552 
29553  (void) duk_push_object_helper(ctx, flags_and_class, bidx_prototype);
29554 
29555  /* If message is undefined, the own property 'message' is not set at
29556  * all to save property space. An empty message is inherited anyway.
29557  */
29558  if (!duk_is_undefined(ctx, 0)) {
29559  duk_to_string(ctx, 0);
29560  duk_dup_0(ctx); /* [ message error message ] */
29561  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
29562  }
29563 
29564  /* Augment the error if called as a normal function. __FILE__ and __LINE__
29565  * are not desirable in this case.
29566  */
29567 
29568 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
29569  if (!duk_is_constructor_call(ctx)) {
29570  duk_err_augment_error_create(thr, thr, NULL, 0, 1 /*noblame_fileline*/);
29571  }
29572 #endif
29573 
29574  return 1;
29575 }
29576 
29577 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx) {
29578  /* XXX: optimize with more direct internal access */
29579 
29580  duk_push_this(ctx);
29581  (void) duk_require_hobject_promote_mask(ctx, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
29582 
29583  /* [ ... this ] */
29584 
29585  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_NAME);
29586  if (duk_is_undefined(ctx, -1)) {
29587  duk_pop(ctx);
29588  duk_push_string(ctx, "Error");
29589  } else {
29590  duk_to_string(ctx, -1);
29591  }
29592 
29593  /* [ ... this name ] */
29594 
29595  /* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
29596  * accident or are they actually needed? The first ToString()
29597  * could conceivably return 'undefined'.
29598  */
29599  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_MESSAGE);
29600  if (duk_is_undefined(ctx, -1)) {
29601  duk_pop(ctx);
29602  duk_push_hstring_empty(ctx);
29603  } else {
29604  duk_to_string(ctx, -1);
29605  }
29606 
29607  /* [ ... this name message ] */
29608 
29609  if (duk_get_length(ctx, -2) == 0) {
29610  /* name is empty -> return message */
29611  return 1;
29612  }
29613  if (duk_get_length(ctx, -1) == 0) {
29614  /* message is empty -> return name */
29615  duk_pop(ctx);
29616  return 1;
29617  }
29618  duk_push_string(ctx, ": ");
29619  duk_insert(ctx, -2); /* ... name ': ' message */
29620  duk_concat(ctx, 3);
29621 
29622  return 1;
29623 }
29624 
29625 #if defined(DUK_USE_TRACEBACKS)
29626 
29627 /*
29628  * Traceback handling
29629  *
29630  * The unified helper decodes the traceback and produces various requested
29631  * outputs. It should be optimized for size, and may leave garbage on stack,
29632  * only the topmost return value matters. For instance, traceback separator
29633  * and decoded strings are pushed even when looking for filename only.
29634  *
29635  * NOTE: although _Tracedata is an internal property, user code can currently
29636  * write to the array (or replace it with something other than an array).
29637  * The code below must tolerate arbitrary _Tracedata. It can throw errors
29638  * etc, but cannot cause a segfault or memory unsafe behavior.
29639  */
29640 
29641 /* constants arbitrary, chosen for small loads */
29642 #define DUK__OUTPUT_TYPE_TRACEBACK (-1)
29643 #define DUK__OUTPUT_TYPE_FILENAME 0
29644 #define DUK__OUTPUT_TYPE_LINENUMBER 1
29645 
29646 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_context *ctx, duk_small_int_t output_type) {
29647  duk_hthread *thr = (duk_hthread *) ctx;
29648  duk_idx_t idx_td;
29649  duk_small_int_t i; /* traceback depth fits into 16 bits */
29650  duk_small_int_t t; /* stack type fits into 16 bits */
29651  duk_small_int_t count_func = 0; /* traceback depth ensures fits into 16 bits */
29652  const char *str_tailcall = " tailcall";
29653  const char *str_strict = " strict";
29654  const char *str_construct = " construct";
29655  const char *str_prevyield = " preventsyield";
29656  const char *str_directeval = " directeval";
29657  const char *str_empty = "";
29658 
29659  DUK_ASSERT_TOP(ctx, 0); /* fixed arg count */
29660  DUK_UNREF(thr);
29661 
29662  duk_push_this(ctx);
29663  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_TRACEDATA);
29664  idx_td = duk_get_top_index(ctx);
29665 
29666  duk_push_hstring_stridx(ctx, DUK_STRIDX_NEWLINE_4SPACE);
29667  duk_push_this(ctx);
29668 
29669  /* [ ... this tracedata sep this ] */
29670 
29671  /* XXX: skip null filename? */
29672 
29673  if (duk_check_type(ctx, idx_td, DUK_TYPE_OBJECT)) {
29674  /* Current tracedata contains 2 entries per callstack entry. */
29675  for (i = 0; ; i += 2) {
29676  duk_int_t pc;
29677  duk_int_t line;
29678  duk_int_t flags;
29679  duk_double_t d;
29680  const char *funcname;
29681  const char *filename;
29682  duk_hobject *h_func;
29683  duk_hstring *h_name;
29684 
29685  duk_require_stack(ctx, 5);
29686  duk_get_prop_index(ctx, idx_td, i);
29687  duk_get_prop_index(ctx, idx_td, i + 1);
29688  d = duk_to_number_m1(ctx);
29689  pc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);
29690  flags = (duk_int_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);
29691  t = (duk_small_int_t) duk_get_type(ctx, -2);
29692 
29693  if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
29694  /*
29695  * Ecmascript/native function call or lightfunc call
29696  */
29697 
29698  count_func++;
29699 
29700  /* [ ... v1(func) v2(pc+flags) ] */
29701 
29702  h_func = duk_get_hobject(ctx, -2); /* NULL for lightfunc */
29703 
29704  /* These may be systematically omitted by Duktape
29705  * with certain config options, but allow user to
29706  * set them on a case-by-case basis.
29707  */
29708  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME);
29709  duk_get_prop_stridx_short(ctx, -3, DUK_STRIDX_FILE_NAME);
29710 
29711 #if defined(DUK_USE_PC2LINE)
29712  line = duk_hobject_pc2line_query(ctx, -4, (duk_uint_fast32_t) pc);
29713 #else
29714  line = 0;
29715 #endif
29716 
29717  /* [ ... v1 v2 name filename ] */
29718 
29719  /* When looking for .fileName/.lineNumber, blame first
29720  * function which has a .fileName.
29721  */
29722  if (duk_is_string_notsymbol(ctx, -1)) {
29723  if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
29724  return 1;
29725  } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
29726  duk_push_int(ctx, line);
29727  return 1;
29728  }
29729  }
29730 
29731  /* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
29732  /* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
29733  h_name = duk_get_hstring_notsymbol(ctx, -2); /* may be NULL */
29734  funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
29735  "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
29736  filename = duk_get_string_notsymbol(ctx, -1);
29737  filename = filename ? filename : "";
29738  DUK_ASSERT(funcname != NULL);
29739  DUK_ASSERT(filename != NULL);
29740 
29741  if (h_func == NULL) {
29742  duk_push_sprintf(ctx, "at %s light%s%s%s%s%s",
29743  (const char *) funcname,
29744  (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
29745  (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
29746  (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
29747  (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
29748  (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
29749  } else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
29750  duk_push_sprintf(ctx, "at %s (%s) native%s%s%s%s%s",
29751  (const char *) funcname,
29752  (const char *) filename,
29753  (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
29754  (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
29755  (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
29756  (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
29757  (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
29758  } else {
29759  duk_push_sprintf(ctx, "at %s (%s:%ld)%s%s%s%s%s",
29760  (const char *) funcname,
29761  (const char *) filename,
29762  (long) line,
29763  (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
29764  (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
29765  (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
29766  (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
29767  (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
29768  }
29769  duk_replace(ctx, -5); /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
29770  duk_pop_3(ctx); /* -> [ ... str ] */
29771  } else if (t == DUK_TYPE_STRING) {
29772  const char *str_file;
29773 
29774  /*
29775  * __FILE__ / __LINE__ entry, here 'pc' is line number directly.
29776  * Sometimes __FILE__ / __LINE__ is reported as the source for
29777  * the error (fileName, lineNumber), sometimes not.
29778  */
29779 
29780  /* [ ... v1(filename) v2(line+flags) ] */
29781 
29782  /* When looking for .fileName/.lineNumber, blame compilation
29783  * or C call site unless flagged not to do so.
29784  */
29785  if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
29786  if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
29787  duk_pop(ctx);
29788  return 1;
29789  } else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
29790  duk_push_int(ctx, pc);
29791  return 1;
29792  }
29793  }
29794 
29795  /* Tracedata is trusted but avoid any risk of using a NULL
29796  * for %s format because it has undefined behavior. Symbols
29797  * don't need to be explicitly rejected as they pose no memory
29798  * safety issues.
29799  */
29800  str_file = (const char *) duk_get_string(ctx, -2);
29801  duk_push_sprintf(ctx, "at [anon] (%s:%ld) internal",
29802  (const char *) (str_file ? str_file : "null"), (long) pc);
29803  duk_replace(ctx, -3); /* [ ... v1 v2 str ] -> [ ... str v2 ] */
29804  duk_pop(ctx); /* -> [ ... str ] */
29805  } else {
29806  /* unknown, ignore */
29807  duk_pop_2(ctx);
29808  break;
29809  }
29810  }
29811 
29812  if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
29813  /* Possibly truncated; there is no explicit truncation
29814  * marker so this is the best we can do.
29815  */
29816 
29817  duk_push_hstring_stridx(ctx, DUK_STRIDX_BRACKETED_ELLIPSIS);
29818  }
29819  }
29820 
29821  /* [ ... this tracedata sep this str1 ... strN ] */
29822 
29823  if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
29824  return 0;
29825  } else {
29826  /* The 'this' after 'sep' will get ToString() coerced by
29827  * duk_join() automatically. We don't want to do that
29828  * coercion when providing .fileName or .lineNumber (GH-254).
29829  */
29830  duk_join(ctx, duk_get_top(ctx) - (idx_td + 2) /*count, not including sep*/);
29831  return 1;
29832  }
29833 }
29834 
29835 /* XXX: Output type could be encoded into native function 'magic' value to
29836  * save space. For setters the stridx could be encoded into 'magic'.
29837  */
29838 
29839 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
29840  return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_TRACEBACK);
29841 }
29842 
29843 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
29844  return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_FILENAME);
29845 }
29846 
29847 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
29848  return duk__error_getter_helper(ctx, DUK__OUTPUT_TYPE_LINENUMBER);
29849 }
29850 
29851 #else /* DUK_USE_TRACEBACKS */
29852 
29853 /*
29854  * Traceback handling when tracebacks disabled.
29855  *
29856  * The fileName / lineNumber stubs are now necessary because built-in
29857  * data will include the accessor properties in Error.prototype. If those
29858  * are removed for builds without tracebacks, these can also be removed.
29859  * 'stack' should still be present and produce a ToString() equivalent:
29860  * this is useful for user code which prints a stacktrace and expects to
29861  * see something useful. A normal stacktrace also begins with a ToString()
29862  * of the error so this makes sense.
29863  */
29864 
29865 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx) {
29866  /* XXX: remove this native function and map 'stack' accessor
29867  * to the toString() implementation directly.
29868  */
29869  return duk_bi_error_prototype_to_string(ctx);
29870 }
29871 
29872 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx) {
29873  DUK_UNREF(ctx);
29874  return 0;
29875 }
29876 
29877 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx) {
29878  DUK_UNREF(ctx);
29879  return 0;
29880 }
29881 
29882 #endif /* DUK_USE_TRACEBACKS */
29883 
29884 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_context *ctx, duk_small_uint_t stridx_key) {
29885  /* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
29886  * user code called Object.defineProperty() to create an overriding
29887  * own property. This allows user code to overwrite .fileName etc
29888  * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
29889  * See https://github.com/svaarala/duktape/issues/387.
29890  */
29891 
29892  DUK_ASSERT_TOP(ctx, 1); /* fixed arg count: value */
29893 
29894  duk_push_this(ctx);
29895  duk_push_hstring_stridx(ctx, (duk_small_int_t) stridx_key);
29896  duk_dup_0(ctx);
29897 
29898  /* [ ... obj key value ] */
29899 
29900  DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
29901  duk_get_tval(ctx, -3), duk_get_tval(ctx, -2), duk_get_tval(ctx, -1)));
29902 
29903  duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE |
29904  DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
29905  DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
29906  DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
29907  return 0;
29908 }
29909 
29910 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx) {
29911  return duk__error_setter_helper(ctx, DUK_STRIDX_STACK);
29912 }
29913 
29914 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx) {
29915  return duk__error_setter_helper(ctx, DUK_STRIDX_FILE_NAME);
29916 }
29917 
29918 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx) {
29919  return duk__error_setter_helper(ctx, DUK_STRIDX_LINE_NUMBER);
29920 }
29921 
29922 /* automatic undefs */
29923 #undef DUK__OUTPUT_TYPE_FILENAME
29924 #undef DUK__OUTPUT_TYPE_LINENUMBER
29925 #undef DUK__OUTPUT_TYPE_TRACEBACK
29926 /*
29927  * Function built-ins
29928  */
29929 
29930 /* #include duk_internal.h -> already included */
29931 
29932 /* Needed even when Function built-in is disabled. */
29933 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_context *ctx) {
29934  /* ignore arguments, return undefined (E5 Section 15.3.4) */
29935  DUK_UNREF(ctx);
29936  return 0;
29937 }
29938 
29939 #if defined(DUK_USE_FUNCTION_BUILTIN)
29940 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_context *ctx) {
29941  duk_hthread *thr = (duk_hthread *) ctx;
29942  duk_hstring *h_sourcecode;
29943  duk_idx_t nargs;
29944  duk_idx_t i;
29945  duk_small_uint_t comp_flags;
29946  duk_hcompfunc *func;
29947  duk_hobject *outer_lex_env;
29948  duk_hobject *outer_var_env;
29949 
29950  /* normal and constructor calls have identical semantics */
29951 
29952  nargs = duk_get_top(ctx);
29953  for (i = 0; i < nargs; i++) {
29954  duk_to_string(ctx, i); /* Rejects Symbols during coercion. */
29955  }
29956 
29957  if (nargs == 0) {
29958  duk_push_hstring_empty(ctx);
29959  duk_push_hstring_empty(ctx);
29960  } else if (nargs == 1) {
29961  /* XXX: cover this with the generic >1 case? */
29962  duk_push_hstring_empty(ctx);
29963  } else {
29964  duk_insert(ctx, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
29965  duk_push_string(ctx, ",");
29966  duk_insert(ctx, 1);
29967  duk_join(ctx, nargs - 1);
29968  }
29969 
29970  /* [ body formals ], formals is comma separated list that needs to be parsed */
29971 
29972  DUK_ASSERT_TOP(ctx, 2);
29973 
29974  /* XXX: this placeholder is not always correct, but use for now.
29975  * It will fail in corner cases; see test-dev-func-cons-args.js.
29976  */
29977  duk_push_string(ctx, "function(");
29978  duk_dup_1(ctx);
29979  duk_push_string(ctx, "){");
29980  duk_dup_0(ctx);
29981  duk_push_string(ctx, "}");
29982  duk_concat(ctx, 5);
29983 
29984  /* [ body formals source ] */
29985 
29986  DUK_ASSERT_TOP(ctx, 3);
29987 
29988  /* strictness is not inherited, intentional */
29989  comp_flags = DUK_JS_COMPILE_FLAG_FUNCEXPR;
29990 
29991  duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
29992  h_sourcecode = duk_require_hstring(ctx, -2); /* no symbol check needed; -2 is concat'd code */
29993  duk_js_compile(thr,
29994  (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
29995  (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
29996  comp_flags);
29997 
29998  /* Force .name to 'anonymous' (ES2015). */
29999  duk_push_string(ctx, "anonymous");
30000  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
30001 
30002  func = (duk_hcompfunc *) duk_known_hobject(ctx, -1);
30003  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
30004  DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
30005 
30006  /* [ body formals source template ] */
30007 
30008  /* only outer_lex_env matters, as functions always get a new
30009  * variable declaration environment.
30010  */
30011 
30012  outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
30013  outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
30014 
30015  duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
30016 
30017  /* [ body formals source template closure ] */
30018 
30019  return 1;
30020 }
30021 #endif /* DUK_USE_FUNCTION_BUILTIN */
30022 
30023 #if defined(DUK_USE_FUNCTION_BUILTIN)
30024 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx) {
30025  duk_tval *tv;
30026 
30027  /*
30028  * E5 Section 15.3.4.2 places few requirements on the output of
30029  * this function: the result is implementation dependent, must
30030  * follow FunctionDeclaration syntax (in particular, must have a
30031  * name even for anonymous functions or functions with empty name).
30032  * The output does NOT need to compile into anything useful.
30033  *
30034  * E6 Section 19.2.3.5 changes the requirements completely: the
30035  * result must either eval() to a functionally equivalent object
30036  * OR eval() to a SyntaxError.
30037  *
30038  * We opt for the SyntaxError approach for now, with a syntax that
30039  * mimics V8's native function syntax:
30040  *
30041  * 'function cos() { [native code] }'
30042  *
30043  * but extended with [ecmascript code], [bound code], and
30044  * [lightfunc code].
30045  */
30046 
30047  duk_push_this(ctx);
30048  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
30049  DUK_ASSERT(tv != NULL);
30050 
30051  if (DUK_TVAL_IS_OBJECT(tv)) {
30052  duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
30053  const char *func_name;
30054 
30055  /* Function name: missing/undefined is mapped to empty string,
30056  * otherwise coerce to string. No handling for invalid identifier
30057  * characters or e.g. '{' in the function name. This doesn't
30058  * really matter as long as a SyntaxError results. Technically
30059  * if the name contained a suitable prefix followed by '//' it
30060  * might cause the result to parse without error.
30061  */
30062  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_NAME);
30063  if (duk_is_undefined(ctx, -1)) {
30064  func_name = "";
30065  } else {
30066  func_name = duk_to_string(ctx, -1);
30067  DUK_ASSERT(func_name != NULL);
30068  }
30069 
30070  if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
30071  duk_push_sprintf(ctx, "function %s() { [ecmascript code] }", (const char *) func_name);
30072  } else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
30073  duk_push_sprintf(ctx, "function %s() { [native code] }", (const char *) func_name);
30074  } else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
30075  duk_push_sprintf(ctx, "function %s() { [bound code] }", (const char *) func_name);
30076  } else {
30077  goto type_error;
30078  }
30079  } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
30080  duk_push_lightfunc_tostring(ctx, tv);
30081  } else {
30082  goto type_error;
30083  }
30084 
30085  return 1;
30086 
30087  type_error:
30088  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
30089 }
30090 #endif
30091 
30092 #if defined(DUK_USE_FUNCTION_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
30093 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx) {
30094  /*
30095  * magic = 0: Function.prototype.apply()
30096  * magic = 1: Reflect.apply()
30097  * magic = 2: Reflect.construct()
30098  */
30099 
30100  duk_idx_t idx_args;
30101  duk_idx_t len;
30102  duk_idx_t i;
30103  duk_int_t magic;
30104  duk_idx_t nargs;
30105  duk_uint_t mask;
30106 
30107  magic = duk_get_current_magic(ctx);
30108  switch (magic) {
30109  case 0: /* Function.prototype.apply() */
30110  DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */
30111  duk_push_this(ctx);
30112  duk_insert(ctx, 0);
30113  /* Fall through intentionally for shared handling. */
30114  case 1: /* Reflect.apply(); Function.prototype.apply() after 'this' fixup. */
30115  DUK_ASSERT_TOP(ctx, 3); /* not a vararg function */
30116  idx_args = 2;
30117  duk_require_callable(ctx, 0);
30118  break;
30119  default: /* Reflect.construct() */
30120  DUK_ASSERT(magic == 2);
30121  duk_require_constructable(ctx, 0);
30122  nargs = duk_get_top(ctx);
30123  if (nargs < 2) {
30124  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
30125  }
30126  if (nargs >= 3 && !duk_strict_equals(ctx, 0, 2)) {
30127  /* XXX: [[Construct]] newTarget currently unsupported */
30128  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
30129  }
30130  idx_args = 1;
30131  break;
30132  }
30133 
30134  if (magic != 2) {
30135  DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
30136  (duk_tval *) duk_get_tval(ctx, 0),
30137  (duk_tval *) duk_get_tval(ctx, 1),
30138  (duk_tval *) duk_get_tval(ctx, 2)));
30139  } else {
30140  /* thisArg is not applicable for Reflect.construct(). */
30141  DUK_DDD(DUK_DDDPRINT("func=%!iT, argArray=%!iT",
30142  (duk_tval *) duk_get_tval(ctx, 0),
30143  (duk_tval *) duk_get_tval(ctx, 1)));
30144  }
30145 
30146  /* [ func thisArg? argArray ] */
30147 
30148  mask = duk_get_type_mask(ctx, idx_args);
30149  if (mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) {
30150  DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
30151  len = 0;
30152  } else if (mask & DUK_TYPE_MASK_OBJECT) {
30153  DUK_DDD(DUK_DDDPRINT("argArray is an object"));
30154 
30155  /* XXX: make this an internal helper */
30156  DUK_ASSERT(idx_args >= 0 && idx_args <= 0x7fffL); /* short variants would work, but avoid shifting */
30157  duk_get_prop_stridx(ctx, idx_args, DUK_STRIDX_LENGTH);
30158  len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */
30159  duk_pop(ctx);
30160 
30161  duk_require_stack(ctx, len);
30162 
30163  DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
30164  for (i = 0; i < len; i++) {
30165  duk_get_prop_index(ctx, idx_args, i);
30166  }
30167  } else {
30168  goto type_error;
30169  }
30170  duk_remove(ctx, idx_args);
30171  DUK_ASSERT_TOP(ctx, idx_args + len);
30172 
30173  /* [ func thisArg? arg1 ... argN ] */
30174 
30175  if (magic != 2) {
30176  /* Function.prototype.apply() or Reflect.apply() */
30177  DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
30178  (duk_tval *) duk_get_tval(ctx, 0),
30179  (duk_tval *) duk_get_tval(ctx, 1),
30180  (long) len));
30181  duk_call_method(ctx, len);
30182  } else {
30183  /* Reflect.construct() */
30184  DUK_DDD(DUK_DDDPRINT("construct, func=%!iT, len=%ld",
30185  (duk_tval *) duk_get_tval(ctx, 0),
30186  (long) len));
30187  duk_new(ctx, len);
30188  }
30189  return 1;
30190 
30191  type_error:
30192  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
30193 }
30194 #endif
30195 
30196 #if defined(DUK_USE_FUNCTION_BUILTIN)
30197 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
30198  duk_idx_t nargs;
30199 
30200  /* Step 1 is not necessary because duk_call_method() will take
30201  * care of it.
30202  */
30203 
30204  /* vararg function, thisArg needs special handling */
30205  nargs = duk_get_top(ctx); /* = 1 + arg count */
30206  if (nargs == 0) {
30207  duk_push_undefined(ctx);
30208  nargs++;
30209  }
30210  DUK_ASSERT(nargs >= 1);
30211 
30212  /* [ thisArg arg1 ... argN ] */
30213 
30214  duk_push_this(ctx); /* 'func' in the algorithm */
30215  duk_insert(ctx, 0);
30216 
30217  /* [ func thisArg arg1 ... argN ] */
30218 
30219  DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
30220  (duk_tval *) duk_get_tval(ctx, 0),
30221  (duk_tval *) duk_get_tval(ctx, 1),
30222  (long) (nargs - 1),
30223  (long) duk_get_top(ctx)));
30224  duk_call_method(ctx, nargs - 1);
30225  return 1;
30226 }
30227 #endif /* DUK_USE_FUNCTION_BUILTIN */
30228 
30229 #if defined(DUK_USE_FUNCTION_BUILTIN)
30230 /* XXX: the implementation now assumes "chained" bound functions,
30231  * whereas "collapsed" bound functions (where there is ever only
30232  * one bound function which directly points to a non-bound, final
30233  * function) would require a "collapsing" implementation which
30234  * merges argument lists etc here.
30235  */
30236 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
30237  duk_hthread *thr = (duk_hthread *) ctx;
30238  duk_hobject *h_bound;
30239  duk_hobject *h_target;
30240  duk_idx_t nargs;
30241  duk_idx_t i;
30242 
30243  /* vararg function, careful arg handling (e.g. thisArg may not be present) */
30244  nargs = duk_get_top(ctx); /* = 1 + arg count */
30245  if (nargs == 0) {
30246  duk_push_undefined(ctx);
30247  nargs++;
30248  }
30249  DUK_ASSERT(nargs >= 1);
30250 
30251  duk_push_this(ctx);
30252  duk_require_callable(ctx, -1);
30253 
30254  /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs total) */
30255  DUK_ASSERT_TOP(ctx, nargs + 1);
30256 
30257  /* create bound function object */
30258  h_bound = duk_push_object_helper(ctx,
30259  DUK_HOBJECT_FLAG_EXTENSIBLE |
30260  DUK_HOBJECT_FLAG_BOUNDFUNC |
30261  DUK_HOBJECT_FLAG_CONSTRUCTABLE |
30262  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION),
30263  DUK_BIDX_FUNCTION_PROTOTYPE);
30264  DUK_ASSERT(h_bound != NULL);
30265 
30266  /* [ thisArg arg1 ... argN func boundFunc ] */
30267  duk_dup_m2(ctx); /* func */
30268  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
30269 
30270  duk_dup_0(ctx); /* thisArg */
30271  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);
30272 
30273  duk_push_array(ctx);
30274 
30275  /* [ thisArg arg1 ... argN func boundFunc argArray ] */
30276 
30277  for (i = 0; i < nargs - 1; i++) {
30278  duk_dup(ctx, 1 + i);
30279  duk_put_prop_index(ctx, -2, i);
30280  }
30281  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_ARGS, DUK_PROPDESC_FLAGS_NONE);
30282 
30283  /* [ thisArg arg1 ... argN func boundFunc ] */
30284 
30285  h_target = duk_get_hobject(ctx, -2);
30286 
30287  /* internal prototype must be copied from the target */
30288  if (h_target != NULL) {
30289  /* For lightfuncs Function.prototype is used and is already in place. */
30290  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_bound, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target));
30291  }
30292 
30293  /* bound function 'length' property is interesting */
30294  if (h_target == NULL || /* lightfunc */
30295  DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) {
30296  /* For lightfuncs, simply read the virtual property. */
30297  duk_int_t tmp;
30298  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH);
30299  tmp = duk_to_int(ctx, -1) - (nargs - 1); /* step 15.a */
30300  duk_pop(ctx);
30301  duk_push_int(ctx, (tmp < 0 ? 0 : tmp));
30302  } else {
30303  duk_push_int(ctx, 0);
30304  }
30305  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C); /* attrs in E6 Section 9.2.4 */
30306 
30307  /* caller and arguments must use the same thrower, [[ThrowTypeError]] */
30308  duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_CALLER);
30309  duk_xdef_prop_stridx_thrower(ctx, -1, DUK_STRIDX_LC_ARGUMENTS);
30310 
30311  /* XXX: 'copy properties' API call? */
30312 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
30313  duk_push_string(ctx, "bound "); /* ES2015 19.2.3.2. */
30314  duk_get_prop_stridx_short(ctx, -3, DUK_STRIDX_NAME);
30315  if (!duk_is_string_notsymbol(ctx, -1)) {
30316  /* ES2015 has requirement to check that .name of target is a string
30317  * (also must check for Symbol); if not, targetName should be the
30318  * empty string. ES2015 19.2.3.2.
30319  */
30320  duk_pop(ctx);
30321  duk_push_hstring_empty(ctx);
30322  }
30323  duk_concat(ctx, 2);
30324  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
30325 #endif
30326 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
30327  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_FILE_NAME);
30328  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
30329 #endif
30330 
30331  /* The 'strict' flag is copied to get the special [[Get]] of E5.1
30332  * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
30333  * function. Not sure if this is correct, because the specification
30334  * is a bit ambiguous on this point but it would make sense.
30335  */
30336  if (h_target == NULL) {
30337  /* Lightfuncs are always strict. */
30338  DUK_HOBJECT_SET_STRICT(h_bound);
30339  } else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
30340  DUK_HOBJECT_SET_STRICT(h_bound);
30341  }
30342  DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
30343 
30344  return 1;
30345 }
30346 #endif /* DUK_USE_FUNCTION_BUILTIN */
30347 /*
30348  * Global object built-ins
30349  */
30350 
30351 /* #include duk_internal.h -> already included */
30352 
30353 /*
30354  * Encoding/decoding helpers
30355  */
30356 
30357 /* XXX: Could add fast path (for each transform callback) with direct byte
30358  * lookups (no shifting) and no explicit check for x < 0x80 before table
30359  * lookup.
30360  */
30361 
30362 /* Macros for creating and checking bitmasks for character encoding.
30363  * Bit number is a bit counterintuitive, but minimizes code size.
30364  */
30365 #define DUK__MKBITS(a,b,c,d,e,f,g,h) ((duk_uint8_t) ( \
30366  ((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
30367  ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
30368  ))
30369 #define DUK__CHECK_BITMASK(table,cp) ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
30370 
30371 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
30372 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
30373  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
30374  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
30375  DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x20-0x2f */
30376  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
30377  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
30378  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
30379  DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
30380  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
30381 };
30382 
30383 /* E5.1 Section 15.1.3.4: uriUnescaped */
30384 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
30385  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
30386  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
30387  DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0), /* 0x20-0x2f */
30388  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
30389  DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
30390  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
30391  DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
30392  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0), /* 0x70-0x7f */
30393 };
30394 
30395 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
30396 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
30397  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
30398  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
30399  DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1), /* 0x20-0x2f */
30400  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1), /* 0x30-0x3f */
30401  DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
30402  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
30403  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
30404  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
30405 };
30406 
30407 /* E5.1 Section 15.1.3.2: empty */
30408 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
30409  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
30410  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
30411  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x20-0x2f */
30412  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
30413  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x40-0x4f */
30414  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x50-0x5f */
30415  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x60-0x6f */
30416  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x70-0x7f */
30417 };
30418 
30419 #if defined(DUK_USE_SECTION_B)
30420 /* E5.1 Section B.2.2, step 7. */
30421 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
30422  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x00-0x0f */
30423  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), /* 0x10-0x1f */
30424  DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1), /* 0x20-0x2f */
30425  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0), /* 0x30-0x3f */
30426  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x40-0x4f */
30427  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1), /* 0x50-0x5f */
30428  DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), /* 0x60-0x6f */
30429  DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0) /* 0x70-0x7f */
30430 };
30431 #endif /* DUK_USE_SECTION_B */
30432 
30433 typedef struct {
30434  duk_hthread *thr;
30435  duk_hstring *h_str;
30436  duk_bufwriter_ctx bw;
30437  const duk_uint8_t *p;
30438  const duk_uint8_t *p_start;
30439  const duk_uint8_t *p_end;
30441 
30442 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
30443 
30444 /* XXX: refactor and share with other code */
30445 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
30446  duk_small_int_t ch;
30447  duk_small_int_t t = 0;
30448 
30449  while (n > 0) {
30450  t = t * 16;
30451  ch = (duk_small_int_t) duk_hex_dectab[*p++];
30452  if (DUK_LIKELY(ch >= 0)) {
30453  t += ch;
30454  } else {
30455  return -1;
30456  }
30457  n--;
30458  }
30459  return t;
30460 }
30461 
30462 DUK_LOCAL int duk__transform_helper(duk_context *ctx, duk__transform_callback callback, const void *udata) {
30463  duk_hthread *thr = (duk_hthread *) ctx;
30464  duk__transform_context tfm_ctx_alloc;
30465  duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
30466  duk_codepoint_t cp;
30467 
30468  tfm_ctx->thr = thr;
30469 
30470  tfm_ctx->h_str = duk_to_hstring(ctx, 0);
30471  DUK_ASSERT(tfm_ctx->h_str != NULL);
30472 
30473  DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str)); /* initial size guess */
30474 
30475  tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
30476  tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
30477  tfm_ctx->p = tfm_ctx->p_start;
30478 
30479  while (tfm_ctx->p < tfm_ctx->p_end) {
30480  cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
30481  callback(tfm_ctx, udata, cp);
30482  }
30483 
30484  DUK_BW_COMPACT(thr, &tfm_ctx->bw);
30485 
30486  (void) duk_buffer_to_string(ctx, -1); /* Safe if transform is safe. */
30487  return 1;
30488 }
30489 
30490 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
30491  duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
30492  duk_small_int_t len;
30493  duk_codepoint_t cp1, cp2;
30494  duk_small_int_t i, t;
30495  const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
30496 
30497  /* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
30498  * Codepoint range is restricted so this is a slightly too large
30499  * but doesn't matter.
30500  */
30501  DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
30502 
30503  if (cp < 0) {
30504  goto uri_error;
30505  } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
30506  DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
30507  return;
30508  } else if (cp >= 0xdc00L && cp <= 0xdfffL) {
30509  goto uri_error;
30510  } else if (cp >= 0xd800L && cp <= 0xdbffL) {
30511  /* Needs lookahead */
30512  if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
30513  goto uri_error;
30514  }
30515  if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
30516  goto uri_error;
30517  }
30518  cp1 = cp;
30519  cp = ((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L;
30520  } else if (cp > 0x10ffffL) {
30521  /* Although we can allow non-BMP characters (they'll decode
30522  * back into surrogate pairs), we don't allow extended UTF-8
30523  * characters; they would encode to URIs which won't decode
30524  * back because of strict UTF-8 checks in URI decoding.
30525  * (However, we could just as well allow them here.)
30526  */
30527  goto uri_error;
30528  } else {
30529  /* Non-BMP characters within valid UTF-8 range: encode as is.
30530  * They'll decode back into surrogate pairs if the escaped
30531  * output is decoded.
30532  */
30533  ;
30534  }
30535 
30536  len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
30537  for (i = 0; i < len; i++) {
30538  t = (duk_small_int_t) xutf8_buf[i];
30539  DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
30540  &tfm_ctx->bw,
30541  DUK_ASC_PERCENT,
30542  (duk_uint8_t) duk_uc_nybbles[t >> 4],
30543  (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
30544  }
30545 
30546  return;
30547 
30548  uri_error:
30549  DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
30550 }
30551 
30552 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
30553  const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
30554  duk_small_uint_t utf8_blen;
30555  duk_codepoint_t min_cp;
30556  duk_small_int_t t; /* must be signed */
30557  duk_small_uint_t i;
30558 
30559  /* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
30560  * percent escape path writes max two times CESU-8 encoded BMP length.
30561  */
30562  DUK_BW_ENSURE(tfm_ctx->thr,
30563  &tfm_ctx->bw,
30564  (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
30565  DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
30566 
30567  if (cp == (duk_codepoint_t) '%') {
30568  const duk_uint8_t *p = tfm_ctx->p;
30569  duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
30570 
30571  DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
30572 
30573  if (left < 2) {
30574  goto uri_error;
30575  }
30576 
30577  t = duk__decode_hex_escape(p, 2);
30578  DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
30579  if (t < 0) {
30580  goto uri_error;
30581  }
30582 
30583  if (t < 0x80) {
30584  if (DUK__CHECK_BITMASK(reserved_table, t)) {
30585  /* decode '%xx' to '%xx' if decoded char in reserved set */
30586  DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
30587  DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
30588  &tfm_ctx->bw,
30589  DUK_ASC_PERCENT,
30590  p[0],
30591  p[1]);
30592  } else {
30593  DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
30594  }
30595  tfm_ctx->p += 2;
30596  return;
30597  }
30598 
30599  /* Decode UTF-8 codepoint from a sequence of hex escapes. The
30600  * first byte of the sequence has been decoded to 't'.
30601  *
30602  * Note that UTF-8 validation must be strict according to the
30603  * specification: E5.1 Section 15.1.3, decode algorithm step
30604  * 4.d.vii.8. URIError from non-shortest encodings is also
30605  * specifically noted in the spec.
30606  */
30607 
30608  DUK_ASSERT(t >= 0x80);
30609  if (t < 0xc0) {
30610  /* continuation byte */
30611  goto uri_error;
30612  } else if (t < 0xe0) {
30613  /* 110x xxxx; 2 bytes */
30614  utf8_blen = 2;
30615  min_cp = 0x80L;
30616  cp = t & 0x1f;
30617  } else if (t < 0xf0) {
30618  /* 1110 xxxx; 3 bytes */
30619  utf8_blen = 3;
30620  min_cp = 0x800L;
30621  cp = t & 0x0f;
30622  } else if (t < 0xf8) {
30623  /* 1111 0xxx; 4 bytes */
30624  utf8_blen = 4;
30625  min_cp = 0x10000L;
30626  cp = t & 0x07;
30627  } else {
30628  /* extended utf-8 not allowed for URIs */
30629  goto uri_error;
30630  }
30631 
30632  if (left < utf8_blen * 3 - 1) {
30633  /* '%xx%xx...%xx', p points to char after first '%' */
30634  goto uri_error;
30635  }
30636 
30637  p += 3;
30638  for (i = 1; i < utf8_blen; i++) {
30639  /* p points to digit part ('%xy', p points to 'x') */
30640  t = duk__decode_hex_escape(p, 2);
30641  DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
30642  (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
30643  if (t < 0) {
30644  goto uri_error;
30645  }
30646  if ((t & 0xc0) != 0x80) {
30647  goto uri_error;
30648  }
30649  cp = (cp << 6) + (t & 0x3f);
30650  p += 3;
30651  }
30652  p--; /* p overshoots */
30653  tfm_ctx->p = p;
30654 
30655  DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
30656 
30657  if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
30658  goto uri_error;
30659  }
30660 
30661  /* The E5.1 algorithm checks whether or not a decoded codepoint
30662  * is below 0x80 and perhaps may be in the "reserved" set.
30663  * This seems pointless because the single byte UTF-8 case is
30664  * handled separately, and non-shortest encodings are rejected.
30665  * So, 'cp' cannot be below 0x80 here, and thus cannot be in
30666  * the reserved set.
30667  */
30668 
30669  /* utf-8 validation ensures these */
30670  DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
30671 
30672  if (cp >= 0x10000L) {
30673  cp -= 0x10000L;
30674  DUK_ASSERT(cp < 0x100000L);
30675 
30676  DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
30677  DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffUL) + 0xdc00L));
30678  } else {
30679  DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
30680  }
30681  } else {
30682  DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
30683  }
30684  return;
30685 
30686  uri_error:
30687  DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
30688 }
30689 
30690 #if defined(DUK_USE_SECTION_B)
30691 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
30692  DUK_UNREF(udata);
30693 
30694  DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
30695 
30696  if (cp < 0) {
30697  goto esc_error;
30698  } else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
30699  DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
30700  } else if (cp < 0x100L) {
30701  DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
30702  &tfm_ctx->bw,
30703  (duk_uint8_t) DUK_ASC_PERCENT,
30704  (duk_uint8_t) duk_uc_nybbles[cp >> 4],
30705  (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
30706  } else if (cp < 0x10000L) {
30707  DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
30708  &tfm_ctx->bw,
30709  (duk_uint8_t) DUK_ASC_PERCENT,
30710  (duk_uint8_t) DUK_ASC_LC_U,
30711  (duk_uint8_t) duk_uc_nybbles[cp >> 12],
30712  (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
30713  (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
30714  (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
30715  } else {
30716  /* Characters outside BMP cannot be escape()'d. We could
30717  * encode them as surrogate pairs (for codepoints inside
30718  * valid UTF-8 range, but not extended UTF-8). Because
30719  * escape() and unescape() are legacy functions, we don't.
30720  */
30721  goto esc_error;
30722  }
30723 
30724  return;
30725 
30726  esc_error:
30727  DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
30728 }
30729 
30730 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
30731  duk_small_int_t t;
30732 
30733  DUK_UNREF(udata);
30734 
30735  if (cp == (duk_codepoint_t) '%') {
30736  const duk_uint8_t *p = tfm_ctx->p;
30737  duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p); /* bytes left */
30738 
30739  if (left >= 5 && p[0] == 'u' &&
30740  ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
30741  cp = (duk_codepoint_t) t;
30742  tfm_ctx->p += 5;
30743  } else if (left >= 2 &&
30744  ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
30745  cp = (duk_codepoint_t) t;
30746  tfm_ctx->p += 2;
30747  }
30748  }
30749 
30750  DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
30751 }
30752 #endif /* DUK_USE_SECTION_B */
30753 
30754 /*
30755  * Eval
30756  *
30757  * Eval needs to handle both a "direct eval" and an "indirect eval".
30758  * Direct eval handling needs access to the caller's activation so that its
30759  * lexical environment can be accessed. A direct eval is only possible from
30760  * Ecmascript code; an indirect eval call is possible also from C code.
30761  * When an indirect eval call is made from C code, there may not be a
30762  * calling activation at all which needs careful handling.
30763  */
30764 
30765 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
30766  duk_hthread *thr = (duk_hthread *) ctx;
30767  duk_hstring *h;
30768  duk_activation *act_caller;
30769  duk_activation *act_eval;
30770  duk_activation *act;
30771  duk_hcompfunc *func;
30772  duk_hobject *outer_lex_env;
30773  duk_hobject *outer_var_env;
30774  duk_bool_t this_to_global = 1;
30775  duk_small_uint_t comp_flags;
30776  duk_int_t level = -2;
30777 
30778  DUK_ASSERT(duk_get_top(ctx) == 1 || duk_get_top(ctx) == 2); /* 2 when called by debugger */
30779  DUK_ASSERT(thr->callstack_top >= 1); /* at least this function exists */
30780  DUK_ASSERT(((thr->callstack + thr->callstack_top - 1)->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
30781  (thr->callstack_top >= 2)); /* if direct eval, calling activation must exist */
30782 
30783  /*
30784  * callstack_top - 1 --> this function
30785  * callstack_top - 2 --> caller (may not exist)
30786  *
30787  * If called directly from C, callstack_top might be 1. If calling
30788  * activation doesn't exist, call must be indirect.
30789  */
30790 
30791  h = duk_get_hstring_notsymbol(ctx, 0);
30792  if (!h) {
30793  /* Symbol must be returned as is, like any non-string values. */
30794  return 1; /* return arg as-is */
30795  }
30796 
30797 #if defined(DUK_USE_DEBUGGER_SUPPORT)
30798  /* NOTE: level is used only by the debugger and should never be present
30799  * for an Ecmascript eval().
30800  */
30801  DUK_ASSERT(level == -2); /* by default, use caller's environment */
30802  if (duk_get_top(ctx) >= 2 && duk_is_number(ctx, 1)) {
30803  level = duk_get_int(ctx, 1);
30804  }
30805  DUK_ASSERT(level <= -2); /* This is guaranteed by debugger code. */
30806 #endif
30807 
30808  /* [ source ] */
30809 
30810  comp_flags = DUK_JS_COMPILE_FLAG_EVAL;
30811  act_eval = thr->callstack + thr->callstack_top - 1; /* this function */
30812  if (thr->callstack_top >= (duk_size_t) -level) {
30813  /* Have a calling activation, check for direct eval (otherwise
30814  * assume indirect eval.
30815  */
30816  act_caller = thr->callstack + thr->callstack_top + level; /* caller */
30817  if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
30818  (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
30819  /* Only direct eval inherits strictness from calling code
30820  * (E5.1 Section 10.1.1).
30821  */
30822  comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
30823  }
30824  } else {
30825  DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
30826  }
30827  act_caller = NULL; /* avoid dereference after potential callstack realloc */
30828  act_eval = NULL;
30829 
30830  duk_push_hstring_stridx(ctx, DUK_STRIDX_INPUT); /* XXX: copy from caller? */
30831  duk_js_compile(thr,
30832  (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
30833  (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
30834  comp_flags);
30835  func = (duk_hcompfunc *) duk_known_hobject(ctx, -1);
30836  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
30837 
30838  /* [ source template ] */
30839 
30840  /* E5 Section 10.4.2 */
30841  DUK_ASSERT(thr->callstack_top >= 1);
30842  act = thr->callstack + thr->callstack_top - 1; /* this function */
30843  if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
30844  DUK_ASSERT(thr->callstack_top >= 2);
30845  act = thr->callstack + thr->callstack_top + level; /* caller */
30846  if (act->lex_env == NULL) {
30847  DUK_ASSERT(act->var_env == NULL);
30848  DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
30849 
30850  /* this may have side effects, so re-lookup act */
30851  duk_js_init_activation_environment_records_delayed(thr, act);
30852  act = thr->callstack + thr->callstack_top + level;
30853  }
30854  DUK_ASSERT(act->lex_env != NULL);
30855  DUK_ASSERT(act->var_env != NULL);
30856 
30857  this_to_global = 0;
30858 
30859  if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
30860  duk_hobject *new_env;
30861  duk_hobject *act_lex_env;
30862 
30863  DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
30864  "var_env and lex_env to a fresh env, "
30865  "this_binding to caller's this_binding"));
30866 
30867  act = thr->callstack + thr->callstack_top + level; /* caller */
30868  act_lex_env = act->lex_env;
30869  act = NULL; /* invalidated */
30870 
30871  new_env = duk_push_object_helper_proto(ctx,
30872  DUK_HOBJECT_FLAG_EXTENSIBLE |
30873  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
30874  act_lex_env);
30875  DUK_ASSERT(new_env != NULL);
30876  DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
30877 
30878  outer_lex_env = new_env;
30879  outer_var_env = new_env;
30880 
30881  duk_insert(ctx, 0); /* stash to bottom of value stack to keep new_env reachable for duration of eval */
30882 
30883  /* compiler's responsibility */
30884  DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
30885  } else {
30886  DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
30887  "var_env and lex_env to caller's envs, "
30888  "this_binding to caller's this_binding"));
30889 
30890  outer_lex_env = act->lex_env;
30891  outer_var_env = act->var_env;
30892 
30893  /* compiler's responsibility */
30894  DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
30895  }
30896  } else {
30897  DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
30898  "global object, this_binding to global object"));
30899 
30900  this_to_global = 1;
30901  outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
30902  outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
30903  }
30904  act = NULL;
30905 
30906  /* Eval code doesn't need an automatic .prototype object. */
30907  duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
30908 
30909  /* [ source template closure ] */
30910 
30911  if (this_to_global) {
30912  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
30913  duk_push_hobject_bidx(ctx, DUK_BIDX_GLOBAL);
30914  } else {
30915  duk_tval *tv;
30916  DUK_ASSERT(thr->callstack_top >= 2);
30917  act = thr->callstack + thr->callstack_top + level; /* caller */
30918  tv = thr->valstack + act->idx_bottom - 1; /* this is just beneath bottom */
30919  DUK_ASSERT(tv >= thr->valstack);
30920  duk_push_tval(ctx, tv);
30921  }
30922 
30923  DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
30924  (duk_heaphdr *) outer_lex_env,
30925  (duk_heaphdr *) outer_var_env,
30926  duk_get_tval(ctx, -1)));
30927 
30928  /* [ source template closure this ] */
30929 
30930  duk_call_method(ctx, 0);
30931 
30932  /* [ source template result ] */
30933 
30934  return 1;
30935 }
30936 
30937 /*
30938  * Parsing of ints and floats
30939  */
30940 
30941 #if defined(DUK_USE_GLOBAL_BUILTIN)
30942 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx) {
30943  duk_int32_t radix;
30944  duk_small_uint_t s2n_flags;
30945 
30946  DUK_ASSERT_TOP(ctx, 2);
30947  duk_to_string(ctx, 0); /* Reject symbols. */
30948 
30949  radix = duk_to_int32(ctx, 1);
30950 
30951  /* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
30952  * ES2015 0o123 or 0b10001.
30953  */
30954  s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
30955  DUK_S2N_FLAG_ALLOW_GARBAGE |
30956  DUK_S2N_FLAG_ALLOW_PLUS |
30957  DUK_S2N_FLAG_ALLOW_MINUS |
30958  DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
30959  DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
30960 
30961  /* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
30962  *
30963  * Don't autodetect octals (from leading zeroes), require user code to
30964  * provide an explicit radix 8 for parsing octal. See write-up from Mozilla:
30965  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
30966  */
30967 
30968  if (radix != 0) {
30969  if (radix < 2 || radix > 36) {
30970  goto ret_nan;
30971  }
30972  if (radix != 16) {
30973  s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
30974  }
30975  } else {
30976  radix = 10;
30977  }
30978 
30979  duk_dup_0(ctx);
30980  duk_numconv_parse(ctx, radix, s2n_flags);
30981  return 1;
30982 
30983  ret_nan:
30984  duk_push_nan(ctx);
30985  return 1;
30986 }
30987 #endif /* DUK_USE_GLOBAL_BUILTIN */
30988 
30989 #if defined(DUK_USE_GLOBAL_BUILTIN)
30990 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx) {
30991  duk_small_uint_t s2n_flags;
30992  duk_int32_t radix;
30993 
30994  DUK_ASSERT_TOP(ctx, 1);
30995  duk_to_string(ctx, 0); /* Reject symbols. */
30996 
30997  radix = 10;
30998 
30999  /* XXX: check flags */
31000  s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
31001  DUK_S2N_FLAG_ALLOW_EXP |
31002  DUK_S2N_FLAG_ALLOW_GARBAGE |
31003  DUK_S2N_FLAG_ALLOW_PLUS |
31004  DUK_S2N_FLAG_ALLOW_MINUS |
31005  DUK_S2N_FLAG_ALLOW_INF |
31006  DUK_S2N_FLAG_ALLOW_FRAC |
31007  DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
31008  DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
31009  DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
31010 
31011  duk_numconv_parse(ctx, radix, s2n_flags);
31012  return 1;
31013 }
31014 #endif /* DUK_USE_GLOBAL_BUILTIN */
31015 
31016 /*
31017  * Number checkers
31018  */
31019 
31020 #if defined(DUK_USE_GLOBAL_BUILTIN)
31021 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx) {
31022  duk_double_t d = duk_to_number(ctx, 0);
31023  duk_push_boolean(ctx, DUK_ISNAN(d));
31024  return 1;
31025 }
31026 #endif /* DUK_USE_GLOBAL_BUILTIN */
31027 
31028 #if defined(DUK_USE_GLOBAL_BUILTIN)
31029 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx) {
31030  duk_double_t d = duk_to_number(ctx, 0);
31031  duk_push_boolean(ctx, DUK_ISFINITE(d));
31032  return 1;
31033 }
31034 #endif /* DUK_USE_GLOBAL_BUILTIN */
31035 
31036 /*
31037  * URI handling
31038  */
31039 
31040 #if defined(DUK_USE_GLOBAL_BUILTIN)
31041 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx) {
31042  return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
31043 }
31044 
31045 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx) {
31046  return duk__transform_helper(ctx, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
31047 }
31048 
31049 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx) {
31050  return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
31051 }
31052 
31053 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx) {
31054  return duk__transform_helper(ctx, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
31055 }
31056 
31057 #if defined(DUK_USE_SECTION_B)
31058 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_context *ctx) {
31059  return duk__transform_helper(ctx, duk__transform_callback_escape, (const void *) NULL);
31060 }
31061 
31062 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx) {
31063  return duk__transform_helper(ctx, duk__transform_callback_unescape, (const void *) NULL);
31064 }
31065 #endif /* DUK_USE_SECTION_B */
31066 #endif /* DUK_USE_GLOBAL_BUILTIN */
31067 
31068 /* automatic undefs */
31069 #undef DUK__CHECK_BITMASK
31070 #undef DUK__MKBITS
31071 /*
31072  * JSON built-ins.
31073  *
31074  * See doc/json.rst.
31075  *
31076  * Codepoints are handled as duk_uint_fast32_t to ensure that the full
31077  * unsigned 32-bit range is supported. This matters to e.g. JX.
31078  *
31079  * Input parsing doesn't do an explicit end-of-input check at all. This is
31080  * safe: input string data is always NUL-terminated (0x00) and valid JSON
31081  * inputs never contain plain NUL characters, so that as long as syntax checks
31082  * are correct, we'll never read past the NUL. This approach reduces code size
31083  * and improves parsing performance, but it's critical that syntax checks are
31084  * indeed correct!
31085  */
31086 
31087 /* #include duk_internal.h -> already included */
31088 
31089 #if defined(DUK_USE_JSON_SUPPORT)
31090 
31091 /*
31092  * Local defines and forward declarations.
31093  */
31094 
31095 #define DUK__JSON_DECSTR_BUFSIZE 128
31096 #define DUK__JSON_DECSTR_CHUNKSIZE 64
31097 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
31098 #define DUK__JSON_STRINGIFY_BUFSIZE 128
31099 #define DUK__JSON_MAX_ESC_LEN 10 /* '\Udeadbeef' */
31100 
31101 DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
31102 DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
31103 #if defined(DUK_USE_JX)
31104 DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
31105 #endif
31106 DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
31107 DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
31108 DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
31109 DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
31110 DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
31111 #if defined(DUK_USE_JX)
31112 DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
31113 DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
31114 DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
31115 #endif
31116 DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
31117 DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
31118 DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
31119 DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
31120 DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
31121 DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
31122 DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
31123 
31124 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
31125 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
31126 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
31127 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
31128 #if defined(DUK_USE_FASTINT)
31129 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
31130 #endif
31131 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
31132 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);
31133 DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
31134 DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
31135 DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
31136 DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
31137 DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
31138 DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
31139 DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
31140 DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
31141 DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
31142 #if defined(DUK_USE_FASTINT)
31143 DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
31144 #endif
31145 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
31146 DUK_LOCAL_DECL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
31147 DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
31148 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
31149 DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
31150 #endif
31151 #endif
31152 DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth);
31153 
31154 /*
31155  * Helper tables
31156  */
31157 
31158 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
31159 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
31160  /* 0x00 ... 0x7f: as is
31161  * 0x80: escape generically
31162  * 0x81: slow path
31163  * 0xa0 ... 0xff: backslash + one char
31164  */
31165 
31166  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
31167  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
31168  0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31169  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
31170  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
31171  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
31172  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
31173  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
31174  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31175  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31176  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31177  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31178  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31179  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31180  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
31181  0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
31182 };
31183 #else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
31184 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
31185  DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
31186  DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
31187  DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
31188  DUK_ASC_LC_F, DUK_ASC_LC_R
31189 };
31190 #endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
31191 
31192 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
31193 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
31194  /* 0x00: slow path
31195  * other: as is
31196  */
31197  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31198  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31199  0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31200  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
31201  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
31202  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
31203  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
31204  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
31205  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
31206  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
31207  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
31208  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
31209  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
31210  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
31211  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
31212  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
31213 };
31214 #endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
31215 
31216 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
31217 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
31218  /* 0x00: finish (non-white)
31219  * 0x01: continue
31220  */
31221  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
31222  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31223  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31224  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31225  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31226  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31227  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31228  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31229  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31230  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31231  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31232  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31233  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31234  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31235  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31236  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
31237 };
31238 #endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
31239 
31240 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
31241 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
31242  /* 0x00: finish (not part of number)
31243  * 0x01: continue
31244  */
31245  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31246  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31247  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
31248  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31249  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31250  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31251  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31252  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31253  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31254  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31255  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31256  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31257  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31258  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31259  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31260  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
31261 };
31262 #endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
31263 
31264 /*
31265  * Parsing implementation.
31266  *
31267  * JSON lexer is now separate from duk_lexer.c because there are numerous
31268  * small differences making it difficult to share the lexer.
31269  *
31270  * The parser here works with raw bytes directly; this works because all
31271  * JSON delimiters are ASCII characters. Invalid xUTF-8 encoded values
31272  * inside strings will be passed on without normalization; this is not a
31273  * compliance concern because compliant inputs will always be valid
31274  * CESU-8 encodings.
31275  */
31276 
31277 DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
31278  /* Shared handler to minimize parser size. Cause will be
31279  * hidden, unfortunately, but we'll have an offset which
31280  * is often quite enough.
31281  */
31282  DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
31283  (long) (js_ctx->p - js_ctx->p_start));
31284 }
31285 
31286 DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
31287  const duk_uint8_t *p;
31288  duk_uint8_t t;
31289 
31290  p = js_ctx->p;
31291  for (;;) {
31292  DUK_ASSERT(p <= js_ctx->p_end);
31293  t = *p;
31294 
31295 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
31296  /* This fast path is pretty marginal in practice.
31297  * XXX: candidate for removal.
31298  */
31299  DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00); /* end-of-input breaks */
31300  if (duk__json_eatwhite_lookup[t] == 0) {
31301  break;
31302  }
31303 #else /* DUK_USE_JSON_EATWHITE_FASTPATH */
31304  if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
31305  /* NUL also comes here. Comparison order matters, 0x20
31306  * is most common whitespace.
31307  */
31308  break;
31309  }
31310 #endif /* DUK_USE_JSON_EATWHITE_FASTPATH */
31311  p++;
31312  }
31313  js_ctx->p = p;
31314 }
31315 
31316 #if defined(DUK_USE_JX)
31317 DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
31318  DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
31319  return *js_ctx->p;
31320 }
31321 #endif
31322 
31323 DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
31324  DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
31325  return *js_ctx->p++;
31326 }
31327 
31328 DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
31329  duk__dec_eat_white(js_ctx);
31330  return duk__dec_get(js_ctx);
31331 }
31332 
31333 /* For JX, expressing the whole unsigned 32-bit range matters. */
31334 DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
31335  duk_small_uint_t i;
31336  duk_uint_fast32_t res = 0;
31337  duk_uint8_t x;
31338  duk_small_int_t t;
31339 
31340  for (i = 0; i < n; i++) {
31341  /* XXX: share helper from lexer; duk_lexer.c / hexval(). */
31342 
31343  x = duk__dec_get(js_ctx);
31344  DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
31345  (long) i, (long) n, (long) res, (long) x));
31346 
31347  /* x == 0x00 (EOF) causes syntax_error */
31348  DUK_ASSERT(duk_hex_dectab[0] == -1);
31349  t = duk_hex_dectab[x & 0xff];
31350  if (DUK_LIKELY(t >= 0)) {
31351  res = (res * 16) + t;
31352  } else {
31353  /* catches EOF and invalid digits */
31354  goto syntax_error;
31355  }
31356  }
31357 
31358  DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
31359  return res;
31360 
31361  syntax_error:
31362  duk__dec_syntax_error(js_ctx);
31363  DUK_UNREACHABLE();
31364  return 0;
31365 }
31366 
31367 DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
31368  duk_hstring *h;
31369  const duk_uint8_t *p;
31370  duk_uint8_t x, y;
31371 
31372  /* First character has already been eaten and checked by the caller.
31373  * We can scan until a NUL in stridx string because no built-in strings
31374  * have internal NULs.
31375  */
31376 
31377  DUK_ASSERT_STRIDX_VALID(stridx);
31378  h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
31379  DUK_ASSERT(h != NULL);
31380 
31381  p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
31382  DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1)); /* first character has been matched */
31383 
31384  for (;;) {
31385  x = *p;
31386  if (x == 0) {
31387  break;
31388  }
31389  y = duk__dec_get(js_ctx);
31390  if (x != y) {
31391  /* Catches EOF of JSON input. */
31392  goto syntax_error;
31393  }
31394  p++;
31395  }
31396 
31397  return;
31398 
31399  syntax_error:
31400  duk__dec_syntax_error(js_ctx);
31401  DUK_UNREACHABLE();
31402 }
31403 
31404 DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
31405  duk_uint_fast32_t cp;
31406 
31407  /* EOF (-1) will be cast to an unsigned value first
31408  * and then re-cast for the switch. In any case, it
31409  * will match the default case (syntax error).
31410  */
31411  cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
31412  switch (cp) {
31413  case DUK_ASC_BACKSLASH: break;
31414  case DUK_ASC_DOUBLEQUOTE: break;
31415  case DUK_ASC_SLASH: break;
31416  case DUK_ASC_LC_T: cp = 0x09; break;
31417  case DUK_ASC_LC_N: cp = 0x0a; break;
31418  case DUK_ASC_LC_R: cp = 0x0d; break;
31419  case DUK_ASC_LC_F: cp = 0x0c; break;
31420  case DUK_ASC_LC_B: cp = 0x08; break;
31421  case DUK_ASC_LC_U: {
31422  cp = duk__dec_decode_hex_escape(js_ctx, 4);
31423  break;
31424  }
31425 #if defined(DUK_USE_JX)
31426  case DUK_ASC_UC_U: {
31427  if (js_ctx->flag_ext_custom) {
31428  cp = duk__dec_decode_hex_escape(js_ctx, 8);
31429  } else {
31430  return 1; /* syntax error */
31431  }
31432  break;
31433  }
31434  case DUK_ASC_LC_X: {
31435  if (js_ctx->flag_ext_custom) {
31436  cp = duk__dec_decode_hex_escape(js_ctx, 2);
31437  } else {
31438  return 1; /* syntax error */
31439  }
31440  break;
31441  }
31442 #endif /* DUK_USE_JX */
31443  default:
31444  /* catches EOF (0x00) */
31445  return 1; /* syntax error */
31446  }
31447 
31448  DUK_RAW_WRITE_XUTF8(*ext_p, cp);
31449 
31450  return 0;
31451 }
31452 
31453 DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
31454  duk_hthread *thr = js_ctx->thr;
31455  duk_context *ctx = (duk_context *) thr;
31456  duk_bufwriter_ctx bw_alloc;
31457  duk_bufwriter_ctx *bw;
31458  duk_uint8_t *q;
31459 
31460  /* '"' was eaten by caller */
31461 
31462  /* Note that we currently parse -bytes-, not codepoints.
31463  * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
31464  * so they'll simply pass through (valid UTF-8 or not).
31465  */
31466 
31467  bw = &bw_alloc;
31468  DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
31469  q = DUK_BW_GET_PTR(js_ctx->thr, bw);
31470 
31471 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
31472  for (;;) {
31473  duk_small_uint_t safe;
31474  duk_uint8_t b, x;
31475  const duk_uint8_t *p;
31476 
31477  /* Select a safe loop count where no output checks are
31478  * needed assuming we won't encounter escapes. Input
31479  * bound checks are not necessary as a NUL (guaranteed)
31480  * will cause a SyntaxError before we read out of bounds.
31481  */
31482 
31483  safe = DUK__JSON_DECSTR_CHUNKSIZE;
31484 
31485  /* Ensure space for 1:1 output plus one escape. */
31486  q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
31487 
31488  p = js_ctx->p; /* temp copy, write back for next loop */
31489  for (;;) {
31490  if (safe == 0) {
31491  js_ctx->p = p;
31492  break;
31493  }
31494  safe--;
31495 
31496  /* End of input (NUL) goes through slow path and causes SyntaxError. */
31497  DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
31498 
31499  b = *p++;
31500  x = (duk_small_int_t) duk__json_decstr_lookup[b];
31501  if (DUK_LIKELY(x != 0)) {
31502  /* Fast path, decode as is. */
31503  *q++ = b;
31504  } else if (b == DUK_ASC_DOUBLEQUOTE) {
31505  js_ctx->p = p;
31506  goto found_quote;
31507  } else if (b == DUK_ASC_BACKSLASH) {
31508  /* We've ensured space for one escaped input; then
31509  * bail out and recheck (this makes escape handling
31510  * quite slow but it's uncommon).
31511  */
31512  js_ctx->p = p;
31513  if (duk__dec_string_escape(js_ctx, &q) != 0) {
31514  goto syntax_error;
31515  }
31516  break;
31517  } else {
31518  js_ctx->p = p;
31519  goto syntax_error;
31520  }
31521  }
31522  }
31523  found_quote:
31524 #else /* DUK_USE_JSON_DECSTRING_FASTPATH */
31525  for (;;) {
31526  duk_uint8_t x;
31527 
31528  q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
31529 
31530  x = duk__dec_get(js_ctx);
31531 
31532  if (x == DUK_ASC_DOUBLEQUOTE) {
31533  break;
31534  } else if (x == DUK_ASC_BACKSLASH) {
31535  if (duk__dec_string_escape(js_ctx, &q) != 0) {
31536  goto syntax_error;
31537  }
31538  } else if (x < 0x20) {
31539  /* catches EOF (NUL) */
31540  goto syntax_error;
31541  } else {
31542  *q++ = (duk_uint8_t) x;
31543  }
31544  }
31545 #endif /* DUK_USE_JSON_DECSTRING_FASTPATH */
31546 
31547  DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
31548  (void) duk_buffer_to_string(ctx, -1); /* Safe if input string is safe. */
31549 
31550  /* [ ... str ] */
31551 
31552  return;
31553 
31554  syntax_error:
31555  duk__dec_syntax_error(js_ctx);
31556  DUK_UNREACHABLE();
31557 }
31558 
31559 #if defined(DUK_USE_JX)
31560 /* Decode a plain string consisting entirely of identifier characters.
31561  * Used to parse plain keys (e.g. "foo: 123").
31562  */
31563 DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
31564  duk_hthread *thr = js_ctx->thr;
31565  duk_context *ctx = (duk_context *) thr;
31566  const duk_uint8_t *p;
31567  duk_small_int_t x;
31568 
31569  /* Caller has already eaten the first char so backtrack one byte. */
31570 
31571  js_ctx->p--; /* safe */
31572  p = js_ctx->p;
31573 
31574  /* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
31575  * parsing (which is correct except if there are non-shortest encodings).
31576  * There is also no need to check explicitly for end of input buffer as
31577  * the input is NUL padded and NUL will exit the parsing loop.
31578  *
31579  * Because no unescaping takes place, we can just scan to the end of the
31580  * plain string and intern from the input buffer.
31581  */
31582 
31583  for (;;) {
31584  x = *p;
31585 
31586  /* There is no need to check the first character specially here
31587  * (i.e. reject digits): the caller only accepts valid initial
31588  * characters and won't call us if the first character is a digit.
31589  * This also ensures that the plain string won't be empty.
31590  */
31591 
31592  if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
31593  break;
31594  }
31595  p++;
31596  }
31597 
31598  duk_push_lstring(ctx, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
31599  js_ctx->p = p;
31600 
31601  /* [ ... str ] */
31602 }
31603 #endif /* DUK_USE_JX */
31604 
31605 #if defined(DUK_USE_JX)
31606 DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
31607  duk_hthread *thr = js_ctx->thr;
31608  duk_context *ctx = (duk_context *) thr;
31609  const duk_uint8_t *p;
31610  duk_small_int_t x;
31611  void *voidptr;
31612 
31613  /* Caller has already eaten the first character ('(') which we don't need. */
31614 
31615  p = js_ctx->p;
31616 
31617  for (;;) {
31618  x = *p;
31619 
31620  /* Assume that the native representation never contains a closing
31621  * parenthesis.
31622  */
31623 
31624  if (x == DUK_ASC_RPAREN) {
31625  break;
31626  } else if (x <= 0) {
31627  /* NUL term or -1 (EOF), NUL check would suffice */
31628  goto syntax_error;
31629  }
31630  p++;
31631  }
31632 
31633  /* There is no need to NUL delimit the sscanf() call: trailing garbage is
31634  * ignored and there is always a NUL terminator which will force an error
31635  * if no error is encountered before it. It's possible that the scan
31636  * would scan further than between [js_ctx->p,p[ though and we'd advance
31637  * by less than the scanned value.
31638  *
31639  * Because pointers are platform specific, a failure to scan a pointer
31640  * results in a null pointer which is a better placeholder than a missing
31641  * value or an error.
31642  */
31643 
31644  voidptr = NULL;
31645  (void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
31646  duk_push_pointer(ctx, voidptr);
31647  js_ctx->p = p + 1; /* skip ')' */
31648 
31649  /* [ ... ptr ] */
31650 
31651  return;
31652 
31653  syntax_error:
31654  duk__dec_syntax_error(js_ctx);
31655  DUK_UNREACHABLE();
31656 }
31657 #endif /* DUK_USE_JX */
31658 
31659 #if defined(DUK_USE_JX)
31660 DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
31661  duk_hthread *thr = js_ctx->thr;
31662  duk_context *ctx = (duk_context *) thr;
31663  const duk_uint8_t *p;
31664  duk_uint8_t *buf;
31665  duk_size_t src_len;
31666  duk_small_int_t x;
31667 
31668  /* Caller has already eaten the first character ('|') which we don't need. */
31669 
31670  p = js_ctx->p;
31671 
31672  /* XXX: Would be nice to share the fast path loop from duk_hex_decode()
31673  * and avoid creating a temporary buffer. However, there are some
31674  * differences which prevent trivial sharing:
31675  *
31676  * - Pipe char detection
31677  * - EOF detection
31678  * - Unknown length of input and output
31679  *
31680  * The best approach here would be a bufwriter and a reasonaly sized
31681  * safe inner loop (e.g. 64 output bytes at a time).
31682  */
31683 
31684  for (;;) {
31685  x = *p;
31686 
31687  /* This loop intentionally does not ensure characters are valid
31688  * ([0-9a-fA-F]) because the hex decode call below will do that.
31689  */
31690  if (x == DUK_ASC_PIPE) {
31691  break;
31692  } else if (x <= 0) {
31693  /* NUL term or -1 (EOF), NUL check would suffice */
31694  goto syntax_error;
31695  }
31696  p++;
31697  }
31698 
31699  /* XXX: this is not very nice; unnecessary copy is made. */
31700  src_len = (duk_size_t) (p - js_ctx->p);
31701  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, src_len);
31702  DUK_ASSERT(buf != NULL);
31703  DUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);
31704  duk_hex_decode(ctx, -1);
31705 
31706  js_ctx->p = p + 1; /* skip '|' */
31707 
31708  /* [ ... buf ] */
31709 
31710  return;
31711 
31712  syntax_error:
31713  duk__dec_syntax_error(js_ctx);
31714  DUK_UNREACHABLE();
31715 }
31716 #endif /* DUK_USE_JX */
31717 
31718 /* Parse a number, other than NaN or +/- Infinity */
31719 DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
31720  duk_context *ctx = (duk_context *) js_ctx->thr;
31721  const duk_uint8_t *p_start;
31722  const duk_uint8_t *p;
31723  duk_uint8_t x;
31724  duk_small_uint_t s2n_flags;
31725 
31726  DUK_DDD(DUK_DDDPRINT("parse_number"));
31727 
31728  p_start = js_ctx->p;
31729 
31730  /* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
31731  * string for strict number parsing.
31732  */
31733 
31734  p = js_ctx->p;
31735  for (;;) {
31736  x = *p;
31737 
31738  DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
31739  (const void *) p_start, (const void *) p,
31740  (const void *) js_ctx->p_end, (long) x));
31741 
31742 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
31743  /* This fast path is pretty marginal in practice.
31744  * XXX: candidate for removal.
31745  */
31746  DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00); /* end-of-input breaks */
31747  if (duk__json_decnumber_lookup[x] == 0) {
31748  break;
31749  }
31750 #else /* DUK_USE_JSON_DECNUMBER_FASTPATH */
31751  if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
31752  (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
31753  x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
31754  /* Plus sign must be accepted for positive exponents
31755  * (e.g. '1.5e+2'). This clause catches NULs.
31756  */
31757  break;
31758  }
31759 #endif /* DUK_USE_JSON_DECNUMBER_FASTPATH */
31760  p++; /* safe, because matched (NUL causes a break) */
31761  }
31762  js_ctx->p = p;
31763 
31764  DUK_ASSERT(js_ctx->p > p_start);
31765  duk_push_lstring(ctx, (const char *) p_start, (duk_size_t) (p - p_start));
31766 
31767  s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
31768  DUK_S2N_FLAG_ALLOW_MINUS | /* but don't allow leading plus */
31769  DUK_S2N_FLAG_ALLOW_FRAC;
31770 
31771  DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
31772  (duk_tval *) duk_get_tval(ctx, -1)));
31773  duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
31774  if (duk_is_nan(ctx, -1)) {
31775  duk__dec_syntax_error(js_ctx);
31776  }
31777  DUK_ASSERT(duk_is_number(ctx, -1));
31778  DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
31779  (duk_tval *) duk_get_tval(ctx, -1)));
31780 
31781  /* [ ... num ] */
31782 }
31783 
31784 DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
31785  duk_context *ctx = (duk_context *) js_ctx->thr;
31786  duk_require_stack(ctx, DUK_JSON_DEC_REQSTACK);
31787 
31788  /* c recursion check */
31789 
31790  DUK_ASSERT(js_ctx->recursion_depth >= 0);
31791  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31792  if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
31793  DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_JSONDEC_RECLIMIT);
31794  }
31795  js_ctx->recursion_depth++;
31796 }
31797 
31798 DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
31799  /* c recursion check */
31800 
31801  DUK_ASSERT(js_ctx->recursion_depth > 0);
31802  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
31803  js_ctx->recursion_depth--;
31804 }
31805 
31806 DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
31807  duk_context *ctx = (duk_context *) js_ctx->thr;
31808  duk_int_t key_count; /* XXX: a "first" flag would suffice */
31809  duk_uint8_t x;
31810 
31811  DUK_DDD(DUK_DDDPRINT("parse_object"));
31812 
31813  duk__dec_objarr_entry(js_ctx);
31814 
31815  duk_push_object(ctx);
31816 
31817  /* Initial '{' has been checked and eaten by caller. */
31818 
31819  key_count = 0;
31820  for (;;) {
31821  x = duk__dec_get_nonwhite(js_ctx);
31822 
31823  DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
31824  (duk_tval *) duk_get_tval(ctx, -1),
31825  (long) x, (long) key_count));
31826 
31827  /* handle comma and closing brace */
31828 
31829  if (x == DUK_ASC_COMMA && key_count > 0) {
31830  /* accept comma, expect new value */
31831  x = duk__dec_get_nonwhite(js_ctx);
31832  } else if (x == DUK_ASC_RCURLY) {
31833  /* eat closing brace */
31834  break;
31835  } else if (key_count == 0) {
31836  /* accept anything, expect first value (EOF will be
31837  * caught by key parsing below.
31838  */
31839  ;
31840  } else {
31841  /* catches EOF (NUL) and initial comma */
31842  goto syntax_error;
31843  }
31844 
31845  /* parse key and value */
31846 
31847  if (x == DUK_ASC_DOUBLEQUOTE) {
31848  duk__dec_string(js_ctx);
31849 #if defined(DUK_USE_JX)
31850  } else if (js_ctx->flag_ext_custom &&
31851  duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
31852  duk__dec_plain_string(js_ctx);
31853 #endif
31854  } else {
31855  goto syntax_error;
31856  }
31857 
31858  /* [ ... obj key ] */
31859 
31860  x = duk__dec_get_nonwhite(js_ctx);
31861  if (x != DUK_ASC_COLON) {
31862  goto syntax_error;
31863  }
31864 
31865  duk__dec_value(js_ctx);
31866 
31867  /* [ ... obj key val ] */
31868 
31869  duk_xdef_prop_wec(ctx, -3);
31870 
31871  /* [ ... obj ] */
31872 
31873  key_count++;
31874  }
31875 
31876  /* [ ... obj ] */
31877 
31878  DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
31879  (duk_tval *) duk_get_tval(ctx, -1)));
31880 
31881  duk__dec_objarr_exit(js_ctx);
31882  return;
31883 
31884  syntax_error:
31885  duk__dec_syntax_error(js_ctx);
31886  DUK_UNREACHABLE();
31887 }
31888 
31889 DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
31890  duk_context *ctx = (duk_context *) js_ctx->thr;
31891  duk_uarridx_t arr_idx;
31892  duk_uint8_t x;
31893 
31894  DUK_DDD(DUK_DDDPRINT("parse_array"));
31895 
31896  duk__dec_objarr_entry(js_ctx);
31897 
31898  duk_push_array(ctx);
31899 
31900  /* Initial '[' has been checked and eaten by caller. */
31901 
31902  arr_idx = 0;
31903  for (;;) {
31904  x = duk__dec_get_nonwhite(js_ctx);
31905 
31906  DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
31907  (duk_tval *) duk_get_tval(ctx, -1),
31908  (long) x, (long) arr_idx));
31909 
31910  /* handle comma and closing bracket */
31911 
31912  if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
31913  /* accept comma, expect new value */
31914  ;
31915  } else if (x == DUK_ASC_RBRACKET) {
31916  /* eat closing bracket */
31917  break;
31918  } else if (arr_idx == 0) {
31919  /* accept anything, expect first value (EOF will be
31920  * caught by duk__dec_value() below.
31921  */
31922  js_ctx->p--; /* backtrack (safe) */
31923  } else {
31924  /* catches EOF (NUL) and initial comma */
31925  goto syntax_error;
31926  }
31927 
31928  /* parse value */
31929 
31930  duk__dec_value(js_ctx);
31931 
31932  /* [ ... arr val ] */
31933 
31934  duk_xdef_prop_index_wec(ctx, -2, arr_idx);
31935  arr_idx++;
31936  }
31937 
31938  /* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
31939  * set the values.
31940  */
31941 
31942  duk_set_length(ctx, -1, arr_idx);
31943 
31944  /* [ ... arr ] */
31945 
31946  DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
31947  (duk_tval *) duk_get_tval(ctx, -1)));
31948 
31949  duk__dec_objarr_exit(js_ctx);
31950  return;
31951 
31952  syntax_error:
31953  duk__dec_syntax_error(js_ctx);
31954  DUK_UNREACHABLE();
31955 }
31956 
31957 DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
31958  duk_context *ctx = (duk_context *) js_ctx->thr;
31959  duk_uint8_t x;
31960 
31961  x = duk__dec_get_nonwhite(js_ctx);
31962 
31963  DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
31964 
31965  /* Note: duk__dec_req_stridx() backtracks one char */
31966 
31967  if (x == DUK_ASC_DOUBLEQUOTE) {
31968  duk__dec_string(js_ctx);
31969  } else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
31970 #if defined(DUK_USE_JX)
31971  if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
31972  duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY); /* "-Infinity", '-' has been eaten */
31973  duk_push_number(ctx, -DUK_DOUBLE_INFINITY);
31974  } else {
31975 #else
31976  { /* unconditional block */
31977 #endif
31978  /* We already ate 'x', so backup one byte. */
31979  js_ctx->p--; /* safe */
31980  duk__dec_number(js_ctx);
31981  }
31982  } else if (x == DUK_ASC_LC_T) {
31983  duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
31984  duk_push_true(ctx);
31985  } else if (x == DUK_ASC_LC_F) {
31986  duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
31987  duk_push_false(ctx);
31988  } else if (x == DUK_ASC_LC_N) {
31989  duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
31990  duk_push_null(ctx);
31991 #if defined(DUK_USE_JX)
31992  } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
31993  duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
31994  duk_push_undefined(ctx);
31995  } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
31996  duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
31997  duk_push_nan(ctx);
31998  } else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
31999  duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
32000  duk_push_number(ctx, DUK_DOUBLE_INFINITY);
32001  } else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
32002  duk__dec_pointer(js_ctx);
32003  } else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
32004  duk__dec_buffer(js_ctx);
32005 #endif
32006  } else if (x == DUK_ASC_LCURLY) {
32007  duk__dec_object(js_ctx);
32008  } else if (x == DUK_ASC_LBRACKET) {
32009  duk__dec_array(js_ctx);
32010  } else {
32011  /* catches EOF (NUL) */
32012  goto syntax_error;
32013  }
32014 
32015  duk__dec_eat_white(js_ctx);
32016 
32017  /* [ ... val ] */
32018  return;
32019 
32020  syntax_error:
32021  duk__dec_syntax_error(js_ctx);
32022  DUK_UNREACHABLE();
32023 }
32024 
32025 /* Recursive value reviver, implements the Walk() algorithm. No C recursion
32026  * check is done here because the initial parsing step will already ensure
32027  * there is a reasonable limit on C recursion depth and hence object depth.
32028  */
32029 DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
32030  duk_context *ctx = (duk_context *) js_ctx->thr;
32031  duk_hobject *h;
32032  duk_uarridx_t i, arr_len;
32033 
32034  DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
32035  (long) duk_get_top(ctx),
32036  (duk_tval *) duk_get_tval(ctx, -2),
32037  (duk_tval *) duk_get_tval(ctx, -1)));
32038 
32039  duk_dup_top(ctx);
32040  duk_get_prop(ctx, -3); /* -> [ ... holder name val ] */
32041 
32042  h = duk_get_hobject(ctx, -1);
32043  if (h != NULL) {
32044  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
32045  arr_len = (duk_uarridx_t) duk_get_length(ctx, -1);
32046  for (i = 0; i < arr_len; i++) {
32047  /* [ ... holder name val ] */
32048 
32049  DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
32050  (long) duk_get_top(ctx), (long) i, (long) arr_len,
32051  (duk_tval *) duk_get_tval(ctx, -3), (duk_tval *) duk_get_tval(ctx, -2),
32052  (duk_tval *) duk_get_tval(ctx, -1)));
32053 
32054  duk_dup_top(ctx);
32055  (void) duk_push_uint_to_hstring(ctx, (duk_uint_t) i); /* -> [ ... holder name val val ToString(i) ] */
32056  duk__dec_reviver_walk(js_ctx); /* -> [ ... holder name val new_elem ] */
32057 
32058  if (duk_is_undefined(ctx, -1)) {
32059  duk_pop(ctx);
32060  duk_del_prop_index(ctx, -1, i);
32061  } else {
32062  /* XXX: duk_xdef_prop_index_wec() would be more appropriate
32063  * here but it currently makes some assumptions that might
32064  * not hold (e.g. that previous property is not an accessor).
32065  */
32066  duk_put_prop_index(ctx, -2, i);
32067  }
32068  }
32069  } else {
32070  /* [ ... holder name val ] */
32071  duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
32072  while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
32073  DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
32074  (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -5),
32075  (duk_tval *) duk_get_tval(ctx, -4), (duk_tval *) duk_get_tval(ctx, -3),
32076  (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
32077 
32078  /* [ ... holder name val enum obj_key ] */
32079  duk_dup_m3(ctx);
32080  duk_dup_m2(ctx);
32081 
32082  /* [ ... holder name val enum obj_key val obj_key ] */
32083  duk__dec_reviver_walk(js_ctx);
32084 
32085  /* [ ... holder name val enum obj_key new_elem ] */
32086  if (duk_is_undefined(ctx, -1)) {
32087  duk_pop(ctx);
32088  duk_del_prop(ctx, -3);
32089  } else {
32090  /* XXX: duk_xdef_prop_index_wec() would be more appropriate
32091  * here but it currently makes some assumptions that might
32092  * not hold (e.g. that previous property is not an accessor).
32093  *
32094  * Using duk_put_prop() works incorrectly with '__proto__'
32095  * if the own property with that name has been deleted. This
32096  * does not happen normally, but a clever reviver can trigger
32097  * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
32098  */
32099  duk_put_prop(ctx, -4);
32100  }
32101  }
32102  duk_pop(ctx); /* pop enum */
32103  }
32104  }
32105 
32106  /* [ ... holder name val ] */
32107 
32108  duk_dup(ctx, js_ctx->idx_reviver);
32109  duk_insert(ctx, -4); /* -> [ ... reviver holder name val ] */
32110  duk_call_method(ctx, 2); /* -> [ ... res ] */
32111 
32112  DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
32113  (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, -1)));
32114 }
32115 
32116 /*
32117  * Stringify implementation.
32118  */
32119 
32120 #define DUK__EMIT_1(js_ctx,ch) duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
32121 #define DUK__EMIT_2(js_ctx,ch1,ch2) duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
32122 #define DUK__EMIT_HSTR(js_ctx,h) duk__emit_hstring((js_ctx), (h))
32123 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
32124 #define DUK__EMIT_CSTR(js_ctx,p) duk__emit_cstring((js_ctx), (p))
32125 #endif
32126 #define DUK__EMIT_STRIDX(js_ctx,i) duk__emit_stridx((js_ctx), (i))
32127 #define DUK__UNEMIT_1(js_ctx) duk__unemit_1((js_ctx))
32128 
32129 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
32130  DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
32131 }
32132 
32133 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
32134  DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
32135 }
32136 
32137 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
32138  DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
32139 }
32140 
32141 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
32142 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
32143  DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
32144 }
32145 #endif
32146 
32147 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
32148  duk_hstring *h;
32149 
32150  DUK_ASSERT_STRIDX_VALID(stridx);
32151  h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
32152  DUK_ASSERT(h != NULL);
32153 
32154  DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
32155 }
32156 
32157 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
32158  DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
32159  DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
32160 }
32161 
32162 #define DUK__MKESC(nybbles,esc1,esc2) \
32163  (((duk_uint_fast32_t) (nybbles)) << 16) | \
32164  (((duk_uint_fast32_t) (esc1)) << 8) | \
32165  ((duk_uint_fast32_t) (esc2))
32166 
32167 DUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {
32168  duk_uint_fast32_t tmp;
32169  duk_small_uint_t dig;
32170 
32171  DUK_UNREF(js_ctx);
32172 
32173  /* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
32174 
32175  /* Select appropriate escape format automatically, and set 'tmp' to a
32176  * value encoding both the escape format character and the nybble count:
32177  *
32178  * (nybble_count << 16) | (escape_char1) | (escape_char2)
32179  */
32180 
32181 #if defined(DUK_USE_JX)
32182  if (DUK_LIKELY(cp < 0x100UL)) {
32183  if (DUK_UNLIKELY(js_ctx->flag_ext_custom)) {
32184  tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
32185  } else {
32186  tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
32187  }
32188  } else
32189 #endif
32190  if (DUK_LIKELY(cp < 0x10000UL)) {
32191  tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
32192  } else {
32193 #if defined(DUK_USE_JX)
32194  if (DUK_LIKELY(js_ctx->flag_ext_custom)) {
32195  tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
32196  } else
32197 #endif
32198  {
32199  /* In compatible mode and standard JSON mode, output
32200  * something useful for non-BMP characters. This won't
32201  * roundtrip but will still be more or less readable and
32202  * more useful than an error.
32203  */
32204  tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
32205  }
32206  }
32207 
32208  *q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
32209  *q++ = (duk_uint8_t) (tmp & 0xff);
32210 
32211  tmp = tmp >> 16;
32212  while (tmp > 0) {
32213  tmp--;
32214  dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
32215  *q++ = duk_lc_digits[dig];
32216  }
32217 
32218  return q;
32219 }
32220 
32221 DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
32222  const duk_int8_t *p, *p_start, *p_end; /* Note: intentionally signed. */
32223  duk_size_t k_len;
32224  duk_codepoint_t cp;
32225 
32226  DUK_ASSERT(k != NULL);
32227 
32228  /* Accept ASCII strings which conform to identifier requirements
32229  * as being emitted without key quotes. Since we only accept ASCII
32230  * there's no need for actual decoding: 'p' is intentionally signed
32231  * so that bytes >= 0x80 extend to negative values and are rejected
32232  * as invalid identifier codepoints.
32233  */
32234 
32235  if (js_ctx->flag_avoid_key_quotes) {
32236  k_len = DUK_HSTRING_GET_BYTELEN(k);
32237  p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
32238  p_end = p_start + k_len;
32239  p = p_start;
32240 
32241  if (p == p_end) {
32242  /* Zero length string is not accepted without quotes */
32243  goto quote_normally;
32244  }
32245  cp = (duk_codepoint_t) (*p++);
32246  if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
32247  goto quote_normally;
32248  }
32249  while (p < p_end) {
32250  cp = (duk_codepoint_t) (*p++);
32251  if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
32252  goto quote_normally;
32253  }
32254  }
32255 
32256  /* This seems faster than emitting bytes one at a time and
32257  * then potentially rewinding.
32258  */
32259  DUK__EMIT_HSTR(js_ctx, k);
32260  return;
32261  }
32262 
32263  quote_normally:
32264  duk__enc_quote_string(js_ctx, k);
32265 }
32266 
32267 /* The Quote(value) operation: quote a string.
32268  *
32269  * Stack policy: [ ] -> [ ].
32270  */
32271 
32272 DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
32273  duk_hthread *thr = js_ctx->thr;
32274  const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
32275  duk_uint8_t *q;
32276  duk_ucodepoint_t cp; /* typed for duk_unicode_decode_xutf8() */
32277 
32278  DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
32279 
32280  DUK_ASSERT(h_str != NULL);
32281  p_start = DUK_HSTRING_GET_DATA(h_str);
32282  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
32283  p = p_start;
32284 
32285  DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
32286 
32287  /* Encode string in small chunks, estimating the maximum expansion so that
32288  * there's no need to ensure space while processing the chunk.
32289  */
32290 
32291  while (p < p_end) {
32292  duk_size_t left, now, space;
32293 
32294  left = (duk_size_t) (p_end - p);
32295  now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
32296  DUK__JSON_ENCSTR_CHUNKSIZE : left);
32297 
32298  /* Maximum expansion per input byte is 6:
32299  * - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
32300  * - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
32301  * - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
32302  */
32303  space = now * 6;
32304  q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
32305 
32306  p_now = p + now;
32307 
32308  while (p < p_now) {
32309 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
32310  duk_uint8_t b;
32311 
32312  b = duk__json_quotestr_lookup[*p++];
32313  if (DUK_LIKELY(b < 0x80)) {
32314  /* Most input bytes go through here. */
32315  *q++ = b;
32316  } else if (b >= 0xa0) {
32317  *q++ = DUK_ASC_BACKSLASH;
32318  *q++ = (duk_uint8_t) (b - 0x80);
32319  } else if (b == 0x80) {
32320  cp = (duk_ucodepoint_t) (*(p - 1));
32321  q = duk__emit_esc_auto_fast(js_ctx, cp, q);
32322  } else if (b == 0x7f && js_ctx->flag_ascii_only) {
32323  /* 0x7F is special */
32324  DUK_ASSERT(b == 0x81);
32325  cp = (duk_ucodepoint_t) 0x7f;
32326  q = duk__emit_esc_auto_fast(js_ctx, cp, q);
32327  } else {
32328  DUK_ASSERT(b == 0x81);
32329  p--;
32330 
32331  /* slow path is shared */
32332 #else /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
32333  cp = *p;
32334 
32335  if (DUK_LIKELY(cp <= 0x7f)) {
32336  /* ascii fast path: avoid decoding utf-8 */
32337  p++;
32338  if (cp == 0x22 || cp == 0x5c) {
32339  /* double quote or backslash */
32340  *q++ = DUK_ASC_BACKSLASH;
32341  *q++ = (duk_uint8_t) cp;
32342  } else if (cp < 0x20) {
32343  duk_uint_fast8_t esc_char;
32344 
32345  /* This approach is a bit shorter than a straight
32346  * if-else-ladder and also a bit faster.
32347  */
32348  if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
32349  (esc_char = duk__json_quotestr_esc[cp]) != 0) {
32350  *q++ = DUK_ASC_BACKSLASH;
32351  *q++ = (duk_uint8_t) esc_char;
32352  } else {
32353  q = duk__emit_esc_auto_fast(js_ctx, cp, q);
32354  }
32355  } else if (cp == 0x7f && js_ctx->flag_ascii_only) {
32356  q = duk__emit_esc_auto_fast(js_ctx, cp, q);
32357  } else {
32358  /* any other printable -> as is */
32359  *q++ = (duk_uint8_t) cp;
32360  }
32361  } else {
32362  /* slow path is shared */
32363 #endif /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
32364 
32365  /* slow path decode */
32366 
32367  /* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
32368  * and go forward one byte. This is of course very lossy, but allows some kind
32369  * of output to be produced even for internal strings which don't conform to
32370  * XUTF-8. All standard Ecmascript strings are always CESU-8, so this behavior
32371  * does not violate the Ecmascript specification. The behavior is applied to
32372  * all modes, including Ecmascript standard JSON. Because the current XUTF-8
32373  * decoding is not very strict, this behavior only really affects initial bytes
32374  * and truncated codepoints.
32375  *
32376  * Another alternative would be to scan forwards to start of next codepoint
32377  * (or end of input) and emit just one replacement codepoint.
32378  */
32379 
32380  p_tmp = p;
32381  if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
32382  /* Decode failed. */
32383  cp = *p_tmp;
32384  p = p_tmp + 1;
32385  }
32386 
32387 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
32388  if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
32389 #else
32390  if (js_ctx->flag_ascii_only) {
32391 #endif
32392  q = duk__emit_esc_auto_fast(js_ctx, cp, q);
32393  } else {
32394  /* as is */
32395  DUK_RAW_WRITE_XUTF8(q, cp);
32396  }
32397  }
32398  }
32399 
32400  DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
32401  }
32402 
32403  DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
32404 }
32405 
32406 /* Encode a double (checked by caller) from stack top. Stack top may be
32407  * replaced by serialized string but is not popped (caller does that).
32408  */
32409 DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
32410  duk_hthread *thr;
32411  duk_context *ctx;
32412  duk_tval *tv;
32413  duk_double_t d;
32414  duk_small_int_t c;
32415  duk_small_int_t s;
32416  duk_small_uint_t stridx;
32417  duk_small_uint_t n2s_flags;
32418  duk_hstring *h_str;
32419 
32420  DUK_ASSERT(js_ctx != NULL);
32421  thr = js_ctx->thr;
32422  DUK_ASSERT(thr != NULL);
32423  ctx = (duk_context *) thr;
32424 
32425  /* Caller must ensure 'tv' is indeed a double and not a fastint! */
32426  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
32427  DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
32428  d = DUK_TVAL_GET_DOUBLE(tv);
32429 
32430  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
32431  s = (duk_small_int_t) DUK_SIGNBIT(d);
32432  DUK_UNREF(s);
32433 
32434  if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
32435  DUK_ASSERT(DUK_ISFINITE(d));
32436 
32437 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
32438  /* Negative zero needs special handling in JX/JC because
32439  * it would otherwise serialize to '0', not '-0'.
32440  */
32441  if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
32442  (js_ctx->flag_ext_custom_or_compatible))) {
32443  duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_ZERO); /* '-0' */
32444  } else
32445 #endif /* DUK_USE_JX || DUK_USE_JC */
32446  {
32447  n2s_flags = 0;
32448  /* [ ... number ] -> [ ... string ] */
32449  duk_numconv_stringify(ctx, 10 /*radix*/, 0 /*digits*/, n2s_flags);
32450  }
32451  h_str = duk_known_hstring(ctx, -1);
32452  DUK__EMIT_HSTR(js_ctx, h_str);
32453  return;
32454  }
32455 
32456 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
32457  if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
32458  DUK_JSON_FLAG_EXT_COMPATIBLE))) {
32459  stridx = DUK_STRIDX_LC_NULL;
32460  } else if (c == DUK_FP_NAN) {
32461  stridx = js_ctx->stridx_custom_nan;
32462  } else if (s == 0) {
32463  stridx = js_ctx->stridx_custom_posinf;
32464  } else {
32465  stridx = js_ctx->stridx_custom_neginf;
32466  }
32467 #else
32468  stridx = DUK_STRIDX_LC_NULL;
32469 #endif
32470  DUK__EMIT_STRIDX(js_ctx, stridx);
32471 }
32472 
32473 #if defined(DUK_USE_FASTINT)
32474 /* Encode a fastint from duk_tval ptr, no value stack effects. */
32475 DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
32476  duk_int64_t v;
32477 
32478  /* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
32479  * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
32480  * (20 chars long). Alloc space for 64-bit range to be safe.
32481  */
32482  duk_uint8_t buf[20 + 1];
32483 
32484  /* Caller must ensure 'tv' is indeed a fastint! */
32485  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
32486  v = DUK_TVAL_GET_FASTINT(tv);
32487 
32488  /* XXX: There are no format strings in duk_config.h yet, could add
32489  * one for formatting duk_int64_t. For now, assumes "%lld" and that
32490  * "long long" type exists. Could also rely on C99 directly but that
32491  * won't work for older MSVC.
32492  */
32493  DUK_SPRINTF((char *) buf, "%lld", (long long) v);
32494  DUK__EMIT_CSTR(js_ctx, (const char *) buf);
32495 }
32496 #endif
32497 
32498 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
32499 #if defined(DUK_USE_HEX_FASTPATH)
32500 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
32501  duk_uint8_t *q;
32502  duk_uint16_t *q16;
32503  duk_small_uint_t x;
32504  duk_size_t i, len_safe;
32505 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
32506  duk_bool_t shift_dst;
32507 #endif
32508 
32509  /* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
32510  * For platforms where unaligned accesses are not allowed, shift 'dst'
32511  * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result
32512  * in place. The faster encoding loop makes up the difference.
32513  * There's always space for one extra byte because a terminator always
32514  * follows the hex data and that's been accounted for by the caller.
32515  */
32516 
32517 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
32518  q16 = (duk_uint16_t *) (void *) dst;
32519 #else
32520  shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
32521  if (shift_dst) {
32522  DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
32523  q16 = (duk_uint16_t *) (void *) (dst + 1);
32524  } else {
32525  DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
32526  q16 = (duk_uint16_t *) (void *) dst;
32527  }
32528  DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
32529 #endif
32530 
32531  len_safe = src_len & ~0x03U;
32532  for (i = 0; i < len_safe; i += 4) {
32533  q16[0] = duk_hex_enctab[src[i]];
32534  q16[1] = duk_hex_enctab[src[i + 1]];
32535  q16[2] = duk_hex_enctab[src[i + 2]];
32536  q16[3] = duk_hex_enctab[src[i + 3]];
32537  q16 += 4;
32538  }
32539  q = (duk_uint8_t *) q16;
32540 
32541 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
32542  if (shift_dst) {
32543  q--;
32544  DUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);
32545  DUK_ASSERT(dst + 2 * len_safe == q);
32546  }
32547 #endif
32548 
32549  for (; i < src_len; i++) {
32550  x = src[i];
32551  *q++ = duk_lc_digits[x >> 4];
32552  *q++ = duk_lc_digits[x & 0x0f];
32553  }
32554 
32555  return q;
32556 }
32557 #else /* DUK_USE_HEX_FASTPATH */
32558 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
32559  const duk_uint8_t *p;
32560  const duk_uint8_t *p_end;
32561  duk_uint8_t *q;
32562  duk_small_uint_t x;
32563 
32564  p = src;
32565  p_end = src + src_len;
32566  q = dst;
32567  while (p != p_end) {
32568  x = *p++;
32569  *q++ = duk_lc_digits[x >> 4];
32570  *q++ = duk_lc_digits[x & 0x0f];
32571  }
32572 
32573  return q;
32574 }
32575 #endif /* DUK_USE_HEX_FASTPATH */
32576 
32577 DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
32578  duk_hthread *thr;
32579  duk_uint8_t *q;
32580  duk_size_t space;
32581 
32582  thr = js_ctx->thr;
32583 
32584  DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
32585  DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
32586 
32587  /* Buffer values are encoded in (lowercase) hex to make the
32588  * binary data readable. Base64 or similar would be more
32589  * compact but less readable, and the point of JX/JC
32590  * variants is to be as useful to a programmer as possible.
32591  */
32592 
32593  /* The #if defined() clutter here needs to handle the three
32594  * cases: (1) JX+JC, (2) JX only, (3) JC only.
32595  */
32596 
32597  /* Note: space must cater for both JX and JC. */
32598  space = 9 + buf_len * 2 + 2;
32599  DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
32600  DUK_ASSERT((space - 2) / 2 >= buf_len); /* overflow not possible, buffer limits */
32601  q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
32602 
32603 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
32604  if (js_ctx->flag_ext_custom)
32605 #endif
32606 #if defined(DUK_USE_JX)
32607  {
32608  *q++ = DUK_ASC_PIPE;
32609  q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
32610  *q++ = DUK_ASC_PIPE;
32611 
32612  }
32613 #endif
32614 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
32615  else
32616 #endif
32617 #if defined(DUK_USE_JC)
32618  {
32619  DUK_ASSERT(js_ctx->flag_ext_compatible);
32620  DUK_MEMCPY((void *) q, (const void *) "{\"_buf\":\"", 9); /* len: 9 */
32621  q += 9;
32622  q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
32623  *q++ = DUK_ASC_DOUBLEQUOTE;
32624  *q++ = DUK_ASC_RCURLY;
32625  }
32626 #endif
32627 
32628  DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
32629 }
32630 
32631 DUK_LOCAL void duk__enc_buffer(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
32632  duk__enc_buffer_data(js_ctx,
32633  (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
32634  (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
32635 }
32636 #endif /* DUK_USE_JX || DUK_USE_JC */
32637 
32638 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
32639 DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
32640  char buf[64]; /* XXX: how to figure correct size? */
32641  const char *fmt;
32642 
32643  DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible); /* caller checks */
32644  DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
32645 
32646  DUK_MEMZERO(buf, sizeof(buf));
32647 
32648  /* The #if defined() clutter here needs to handle the three
32649  * cases: (1) JX+JC, (2) JX only, (3) JC only.
32650  */
32651 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
32652  if (js_ctx->flag_ext_custom)
32653 #endif
32654 #if defined(DUK_USE_JX)
32655  {
32656  fmt = ptr ? "(%p)" : "(null)";
32657  }
32658 #endif
32659 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
32660  else
32661 #endif
32662 #if defined(DUK_USE_JC)
32663  {
32664  DUK_ASSERT(js_ctx->flag_ext_compatible);
32665  fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
32666  }
32667 #endif
32668 
32669  /* When ptr == NULL, the format argument is unused. */
32670  DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr); /* must not truncate */
32671  DUK__EMIT_CSTR(js_ctx, buf);
32672 }
32673 #endif /* DUK_USE_JX || DUK_USE_JC */
32674 
32675 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
32676 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
32677 DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
32678  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
32679 
32680  if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
32681  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
32682  } else {
32683  /* Handle both full and partial slice (as long as covered). */
32684  duk__enc_buffer_data(js_ctx,
32685  (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
32686  (duk_size_t) h_bufobj->length);
32687  }
32688 }
32689 #endif /* DUK_USE_JX || DUK_USE_JC */
32690 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
32691 
32692 /* Indent helper. Calling code relies on js_ctx->recursion_depth also being
32693  * directly related to indent depth.
32694  */
32695 #if defined(DUK_USE_PREFER_SIZE)
32696 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
32697  DUK_ASSERT(js_ctx->h_gap != NULL);
32698  DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
32699 
32700  DUK__EMIT_1(js_ctx, 0x0a);
32701  while (depth-- > 0) {
32702  DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
32703  }
32704 }
32705 #else /* DUK_USE_PREFER_SIZE */
32706 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_int_t depth) {
32707  const duk_uint8_t *gap_data;
32708  duk_size_t gap_len;
32709  duk_size_t avail_bytes; /* bytes of indent available for copying */
32710  duk_size_t need_bytes; /* bytes of indent still needed */
32711  duk_uint8_t *p_start;
32712  duk_uint8_t *p;
32713 
32714  DUK_ASSERT(js_ctx->h_gap != NULL);
32715  DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0); /* caller guarantees */
32716 
32717  DUK__EMIT_1(js_ctx, 0x0a);
32718  if (DUK_UNLIKELY(depth == 0)) {
32719  return;
32720  }
32721 
32722  /* To handle deeper indents efficiently, make use of copies we've
32723  * already emitted. In effect we can emit a sequence of 1, 2, 4,
32724  * 8, etc copies, and then finish the last run. Byte counters
32725  * avoid multiply with gap_len on every loop.
32726  */
32727 
32728  gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
32729  gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
32730  DUK_ASSERT(gap_len > 0);
32731 
32732  need_bytes = gap_len * depth;
32733  p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
32734  p_start = p;
32735 
32736  DUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);
32737  p += gap_len;
32738  avail_bytes = gap_len;
32739  DUK_ASSERT(need_bytes >= gap_len);
32740  need_bytes -= gap_len;
32741 
32742  while (need_bytes >= avail_bytes) {
32743  DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);
32744  p += avail_bytes;
32745  need_bytes -= avail_bytes;
32746  avail_bytes <<= 1;
32747  }
32748 
32749  DUK_ASSERT(need_bytes < avail_bytes); /* need_bytes may be zero */
32750  DUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);
32751  p += need_bytes;
32752  /*avail_bytes += need_bytes*/
32753 
32754  DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
32755 }
32756 #endif /* DUK_USE_PREFER_SIZE */
32757 
32758 /* Shared entry handling for object/array serialization. */
32759 DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
32760  duk_context *ctx = (duk_context *) js_ctx->thr;
32761  duk_hobject *h_target;
32762  duk_uint_fast32_t i, n;
32763 
32764  *entry_top = duk_get_top(ctx);
32765 
32766  duk_require_stack(ctx, DUK_JSON_ENC_REQSTACK);
32767 
32768  /* Loop check using a hybrid approach: a fixed-size visited[] array
32769  * with overflow in a loop check object.
32770  */
32771 
32772  h_target = duk_known_hobject(ctx, -1); /* object or array */
32773 
32774  n = js_ctx->recursion_depth;
32775  if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
32776  n = DUK_JSON_ENC_LOOPARRAY;
32777  }
32778  for (i = 0; i < n; i++) {
32779  if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
32780  DUK_DD(DUK_DDPRINT("slow path loop detect"));
32781  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CYCLIC_INPUT);
32782  }
32783  }
32784  if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
32785  js_ctx->visiting[js_ctx->recursion_depth] = h_target;
32786  } else {
32787  duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
32788  duk_dup_top(ctx); /* -> [ ... voidp voidp ] */
32789  if (duk_has_prop(ctx, js_ctx->idx_loop)) {
32790  DUK_ERROR_TYPE((duk_hthread *) ctx, DUK_STR_CYCLIC_INPUT);
32791  }
32792  duk_push_true(ctx); /* -> [ ... voidp true ] */
32793  duk_put_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
32794  }
32795 
32796  /* C recursion check. */
32797 
32798  DUK_ASSERT(js_ctx->recursion_depth >= 0);
32799  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
32800  if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
32801  DUK_ERROR_RANGE((duk_hthread *) ctx, DUK_STR_JSONENC_RECLIMIT);
32802  }
32803  js_ctx->recursion_depth++;
32804 
32805  DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
32806  (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
32807 }
32808 
32809 /* Shared exit handling for object/array serialization. */
32810 DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
32811  duk_context *ctx = (duk_context *) js_ctx->thr;
32812  duk_hobject *h_target;
32813 
32814  /* C recursion check. */
32815 
32816  DUK_ASSERT(js_ctx->recursion_depth > 0);
32817  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
32818  js_ctx->recursion_depth--;
32819 
32820  /* Loop check. */
32821 
32822  h_target = duk_known_hobject(ctx, *entry_top - 1); /* original target at entry_top - 1 */
32823 
32824  if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
32825  /* Previous entry was inside visited[], nothing to do. */
32826  } else {
32827  duk_push_sprintf(ctx, DUK_STR_FMT_PTR, (void *) h_target);
32828  duk_del_prop(ctx, js_ctx->idx_loop); /* -> [ ... ] */
32829  }
32830 
32831  /* Restore stack top after unbalanced code paths. */
32832  duk_set_top(ctx, *entry_top);
32833 
32834  DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
32835  (long) duk_get_top(ctx), (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop)));
32836 }
32837 
32838 /* The JO(value) operation: encode object.
32839  *
32840  * Stack policy: [ object ] -> [ object ].
32841  */
32842 DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
32843  duk_context *ctx = (duk_context *) js_ctx->thr;
32844  duk_hstring *h_key;
32845  duk_idx_t entry_top;
32846  duk_idx_t idx_obj;
32847  duk_idx_t idx_keys;
32848  duk_bool_t emitted;
32849  duk_uarridx_t arr_len, i;
32850  duk_size_t prev_size;
32851 
32852  DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
32853 
32854  duk__enc_objarr_entry(js_ctx, &entry_top);
32855 
32856  idx_obj = entry_top - 1;
32857 
32858  if (js_ctx->idx_proplist >= 0) {
32859  idx_keys = js_ctx->idx_proplist;
32860  } else {
32861  /* XXX: would be nice to enumerate an object at specified index */
32862  duk_dup(ctx, idx_obj);
32863  (void) duk_hobject_get_enumerated_keys(ctx, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/); /* [ ... target ] -> [ ... target keys ] */
32864  idx_keys = duk_require_normalize_index(ctx, -1);
32865  /* leave stack unbalanced on purpose */
32866  }
32867 
32868  DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
32869  (long) idx_keys, (duk_tval *) duk_get_tval(ctx, idx_keys)));
32870 
32871  /* Steps 8-10 have been merged to avoid a "partial" variable. */
32872 
32873  DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
32874 
32875  /* XXX: keys is an internal object with all keys to be processed
32876  * in its (gapless) array part. Because nobody can touch the keys
32877  * object, we could iterate its array part directly (keeping in mind
32878  * that it can be reallocated).
32879  */
32880 
32881  arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_keys);
32882  emitted = 0;
32883  for (i = 0; i < arr_len; i++) {
32884  duk_get_prop_index(ctx, idx_keys, i); /* -> [ ... key ] */
32885 
32886  DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
32887  (duk_tval *) duk_get_tval(ctx, idx_obj),
32888  (duk_tval *) duk_get_tval(ctx, -1)));
32889 
32890  h_key = duk_known_hstring(ctx, -1);
32891  DUK_ASSERT(h_key != NULL);
32892  DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key)); /* proplist filtering; enum options */
32893 
32894  prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
32895  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
32896  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
32897  duk__enc_key_autoquote(js_ctx, h_key);
32898  DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
32899  } else {
32900  duk__enc_key_autoquote(js_ctx, h_key);
32901  DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
32902  }
32903 
32904  /* [ ... key ] */
32905 
32906  if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
32907  /* Value would yield 'undefined', so skip key altogether.
32908  * Side effects have already happened.
32909  */
32910  DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
32911  } else {
32912  DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
32913  emitted = 1;
32914  }
32915 
32916  /* [ ... ] */
32917  }
32918 
32919  if (emitted) {
32920  DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
32921  DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
32922  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
32923  DUK_ASSERT(js_ctx->recursion_depth >= 1);
32924  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
32925  }
32926  }
32927  DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
32928 
32929  duk__enc_objarr_exit(js_ctx, &entry_top);
32930 
32931  DUK_ASSERT_TOP(ctx, entry_top);
32932 }
32933 
32934 /* The JA(value) operation: encode array.
32935  *
32936  * Stack policy: [ array ] -> [ array ].
32937  */
32938 DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
32939  duk_context *ctx = (duk_context *) js_ctx->thr;
32940  duk_idx_t entry_top;
32941  duk_idx_t idx_arr;
32942  duk_bool_t emitted;
32943  duk_uarridx_t i, arr_len;
32944 
32945  DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
32946  (duk_tval *) duk_get_tval(ctx, -1)));
32947 
32948  duk__enc_objarr_entry(js_ctx, &entry_top);
32949 
32950  idx_arr = entry_top - 1;
32951 
32952  /* Steps 8-10 have been merged to avoid a "partial" variable. */
32953 
32954  DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
32955 
32956  arr_len = (duk_uarridx_t) duk_get_length(ctx, idx_arr);
32957  emitted = 0;
32958  for (i = 0; i < arr_len; i++) {
32959  DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
32960  (duk_tval *) duk_get_tval(ctx, idx_arr),
32961  (long) i, (long) arr_len));
32962 
32963  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
32964  DUK_ASSERT(js_ctx->recursion_depth >= 1);
32965  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
32966  }
32967 
32968  (void) duk_push_uint_to_hstring(ctx, (duk_uint_t) i); /* -> [ ... key ] */
32969 
32970  /* [ ... key ] */
32971 
32972  if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
32973  /* Value would normally be omitted, replace with 'null'. */
32974  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
32975  } else {
32976  ;
32977  }
32978 
32979  /* [ ... ] */
32980 
32981  DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
32982  emitted = 1;
32983  }
32984 
32985  if (emitted) {
32986  DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
32987  DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
32988  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
32989  DUK_ASSERT(js_ctx->recursion_depth >= 1);
32990  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
32991  }
32992  }
32993  DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
32994 
32995  duk__enc_objarr_exit(js_ctx, &entry_top);
32996 
32997  DUK_ASSERT_TOP(ctx, entry_top);
32998 }
32999 
33000 /* The Str(key, holder) operation.
33001  *
33002  * Stack policy: [ ... key ] -> [ ... ]
33003  */
33004 DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
33005  duk_context *ctx = (duk_context *) js_ctx->thr;
33006  duk_hthread *thr = (duk_hthread *) ctx;
33007  duk_tval *tv;
33008  duk_tval *tv_holder;
33009  duk_tval *tv_key;
33010  duk_small_int_t c;
33011 
33012  DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
33013  (long) idx_holder, (duk_tval *) duk_get_tval(ctx, idx_holder),
33014  (duk_tval *) duk_get_tval(ctx, -1)));
33015 
33016  DUK_UNREF(thr);
33017 
33018  tv_holder = DUK_GET_TVAL_POSIDX(ctx, idx_holder);
33019  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
33020  tv_key = DUK_GET_TVAL_NEGIDX(ctx, -1);
33021  DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
33022  DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key))); /* Caller responsible. */
33023  (void) duk_hobject_getprop(thr, tv_holder, tv_key);
33024 
33025  /* -> [ ... key val ] */
33026 
33027  DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
33028 
33029  /* Standard JSON checks for .toJSON() only for actual objects; for
33030  * example, setting Number.prototype.toJSON and then serializing a
33031  * number won't invoke the .toJSON() method. However, lightfuncs and
33032  * plain buffers mimic objects so we check for their .toJSON() method.
33033  */
33034  if (duk_check_type_mask(ctx, -1, DUK_TYPE_MASK_OBJECT |
33035  DUK_TYPE_MASK_LIGHTFUNC |
33036  DUK_TYPE_MASK_BUFFER)) {
33037  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_TO_JSON);
33038  if (duk_is_callable(ctx, -1)) { /* toJSON() can also be a lightfunc */
33039  DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
33040  /* XXX: duk_dup_unvalidated(ctx, -2) etc. */
33041  duk_dup_m2(ctx); /* -> [ ... key val toJSON val ] */
33042  duk_dup_m4(ctx); /* -> [ ... key val toJSON val key ] */
33043  duk_call_method(ctx, 1); /* -> [ ... key val val' ] */
33044  duk_remove_m2(ctx); /* -> [ ... key val' ] */
33045  } else {
33046  duk_pop(ctx); /* -> [ ... key val ] */
33047  }
33048  }
33049 
33050  /* [ ... key val ] */
33051 
33052  DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
33053 
33054  if (js_ctx->h_replacer) {
33055  /* XXX: Here a "slice copy" would be useful. */
33056  DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
33057  duk_push_hobject(ctx, js_ctx->h_replacer); /* -> [ ... key val replacer ] */
33058  duk_dup(ctx, idx_holder); /* -> [ ... key val replacer holder ] */
33059  duk_dup_m4(ctx); /* -> [ ... key val replacer holder key ] */
33060  duk_dup_m4(ctx); /* -> [ ... key val replacer holder key val ] */
33061  duk_call_method(ctx, 2); /* -> [ ... key val val' ] */
33062  duk_remove_m2(ctx); /* -> [ ... key val' ] */
33063  }
33064 
33065  /* [ ... key val ] */
33066 
33067  DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
33068 
33069  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
33070  if (DUK_TVAL_IS_OBJECT(tv)) {
33071  duk_hobject *h;
33072 
33073  h = DUK_TVAL_GET_OBJECT(tv);
33074  DUK_ASSERT(h != NULL);
33075 
33076 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
33077 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33078  if (DUK_HOBJECT_IS_BUFOBJ(h) &&
33079  js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
33080  /* With JX/JC a bufferobject gets serialized specially. */
33081  duk_hbufobj *h_bufobj;
33082  h_bufobj = (duk_hbufobj *) h;
33083  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
33084  duk__enc_bufobj(js_ctx, h_bufobj);
33085  goto pop2_emitted;
33086  }
33087  /* Otherwise bufferobjects get serialized as normal objects. */
33088 #endif /* JX || JC */
33089 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
33090  c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
33091  switch (c) {
33092  case DUK_HOBJECT_CLASS_NUMBER: {
33093  DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
33094  duk_to_number_m1(ctx);
33095  /* The coercion potentially invokes user .valueOf() and .toString()
33096  * but can't result in a function value because ToPrimitive() would
33097  * reject such a result: test-dev-json-stringify-coercion-1.js.
33098  */
33099  DUK_ASSERT(!duk_is_callable(ctx, -1));
33100  break;
33101  }
33102  case DUK_HOBJECT_CLASS_STRING: {
33103  DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
33104  duk_to_string(ctx, -1);
33105  /* Same coercion behavior as for Number. */
33106  DUK_ASSERT(!duk_is_callable(ctx, -1));
33107  break;
33108  }
33109 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33110  case DUK_HOBJECT_CLASS_POINTER:
33111 #endif
33112  case DUK_HOBJECT_CLASS_BOOLEAN: {
33113  DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
33114  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
33115  duk_remove_m2(ctx);
33116  break;
33117  }
33118  default: {
33119  /* Normal object which doesn't get automatically coerced to a
33120  * primitive value. Functions are checked for specially. The
33121  * primitive value coercions for Number, String, Pointer, and
33122  * Boolean can't result in functions so suffices to check here.
33123  * Symbol objects are handled like plain objects (their primitive
33124  * value is NOT looked up like for e.g. String objects).
33125  */
33126  DUK_ASSERT(h != NULL);
33127  if (DUK_HOBJECT_IS_CALLABLE(h)) {
33128 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33129  if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
33130  DUK_JSON_FLAG_EXT_COMPATIBLE)) {
33131  /* We only get here when doing non-standard JSON encoding */
33132  DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
33133  DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
33134  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
33135  goto pop2_emitted;
33136  } else {
33137  DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
33138  goto pop2_undef;
33139  }
33140 #else /* DUK_USE_JX || DUK_USE_JC */
33141  DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
33142  goto pop2_undef;
33143 #endif /* DUK_USE_JX || DUK_USE_JC */
33144  }
33145  }
33146  } /* end switch */
33147  }
33148 
33149  /* [ ... key val ] */
33150 
33151  DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(ctx, -1)));
33152 
33153  if (duk_check_type_mask(ctx, -1, js_ctx->mask_for_undefined)) {
33154  /* will result in undefined */
33155  DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
33156  goto pop2_undef;
33157  }
33158  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
33159 
33160  switch (DUK_TVAL_GET_TAG(tv)) {
33161 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33162  /* When JX/JC not in use, the type mask above will avoid this case if needed. */
33163  case DUK_TAG_UNDEFINED: {
33164  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
33165  break;
33166  }
33167 #endif
33168  case DUK_TAG_NULL: {
33169  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
33170  break;
33171  }
33172  case DUK_TAG_BOOLEAN: {
33173  DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
33174  DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
33175  break;
33176  }
33177 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33178  /* When JX/JC not in use, the type mask above will avoid this case if needed. */
33179  case DUK_TAG_POINTER: {
33180  duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
33181  break;
33182  }
33183 #endif /* DUK_USE_JX || DUK_USE_JC */
33184  case DUK_TAG_STRING: {
33185  duk_hstring *h = DUK_TVAL_GET_STRING(tv);
33186  DUK_ASSERT(h != NULL);
33187  if (DUK_HSTRING_HAS_SYMBOL(h)) {
33188  goto pop2_undef;
33189  }
33190  duk__enc_quote_string(js_ctx, h);
33191  break;
33192  }
33193  case DUK_TAG_OBJECT: {
33194  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
33195  DUK_ASSERT(h != NULL);
33196 
33197  /* Function values are handled completely above (including
33198  * coercion results):
33199  */
33200  DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
33201 
33202  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
33203  duk__enc_array(js_ctx);
33204  } else {
33205  duk__enc_object(js_ctx);
33206  }
33207  break;
33208  }
33209  /* Because plain buffers mimics Uint8Array, they have enumerable
33210  * index properties [0,byteLength[. Because JSON only serializes
33211  * enumerable own properties, no properties can be serialized for
33212  * plain buffers (all virtual properties are non-enumerable). However,
33213  * there may be a .toJSON() method which was already handled above.
33214  */
33215  case DUK_TAG_BUFFER: {
33216 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33217  if (js_ctx->flag_ext_custom_or_compatible) {
33218  duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
33219  break;
33220  }
33221 #endif
33222  /* Could implement a fast path, but object coerce and
33223  * serialize the result for now.
33224  */
33225  duk_to_object(ctx, -1);
33226  duk__enc_object(js_ctx);
33227  break;
33228  }
33229  case DUK_TAG_LIGHTFUNC: {
33230 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33231  /* We only get here when doing non-standard JSON encoding */
33232  DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
33233  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
33234 #else
33235  /* Standard JSON omits functions */
33236  DUK_UNREACHABLE();
33237 #endif
33238  break;
33239  }
33240 #if defined(DUK_USE_FASTINT)
33241  case DUK_TAG_FASTINT:
33242  /* Number serialization has a significant impact relative to
33243  * other fast path code, so careful fast path for fastints.
33244  */
33245  duk__enc_fastint_tval(js_ctx, tv);
33246  break;
33247 #endif
33248  default: {
33249  /* number */
33250  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
33251  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
33252  /* XXX: A fast path for usual integers would be useful when
33253  * fastint support is not enabled.
33254  */
33255  duk__enc_double(js_ctx);
33256  break;
33257  }
33258  }
33259 
33260 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33261  pop2_emitted:
33262 #endif
33263  duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
33264  return 1; /* emitted */
33265 
33266  pop2_undef:
33267  duk_pop_2(ctx); /* [ ... key val ] -> [ ... ] */
33268  return 0; /* not emitted */
33269 }
33270 
33271 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
33272 DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
33273  duk_small_int_t c;
33274 
33275  /* XXX: some kind of external internal type checker?
33276  * - type mask; symbol flag; class mask
33277  */
33278  DUK_ASSERT(tv != NULL);
33279  if (DUK_TVAL_IS_STRING(tv)) {
33280  duk_hstring *h;
33281  h = DUK_TVAL_GET_STRING(tv);
33282  DUK_ASSERT(h != NULL);
33283  if (DUK_HSTRING_HAS_SYMBOL(h)) {
33284  return 0;
33285  }
33286  return 1;
33287  } else if (DUK_TVAL_IS_NUMBER(tv)) {
33288  return 1;
33289  } else if (DUK_TVAL_IS_OBJECT(tv)) {
33290  duk_hobject *h;
33291  h = DUK_TVAL_GET_OBJECT(tv);
33292  DUK_ASSERT(h != NULL);
33293  c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
33294  if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
33295  return 1;
33296  }
33297  }
33298 
33299  return 0;
33300 }
33301 
33302 /*
33303  * JSON.stringify() fast path
33304  *
33305  * Otherwise supports full JSON, JX, and JC features, but bails out on any
33306  * possible side effect which might change the value being serialized. The
33307  * fast path can take advantage of the fact that the value being serialized
33308  * is unchanged so that we can walk directly through property tables etc.
33309  */
33310 
33311 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
33312 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
33313  duk_uint_fast32_t i, n;
33314 
33315  DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
33316 
33317  DUK_ASSERT(js_ctx != NULL);
33318  DUK_ASSERT(js_ctx->thr != NULL);
33319 
33320 #if 0 /* disabled for now */
33321  restart_match:
33322 #endif
33323 
33324  DUK_ASSERT(tv != NULL);
33325 
33326  switch (DUK_TVAL_GET_TAG(tv)) {
33327  case DUK_TAG_UNDEFINED: {
33328 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33329  if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
33330  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
33331  break;
33332  } else {
33333  goto emit_undefined;
33334  }
33335 #else
33336  goto emit_undefined;
33337 #endif
33338  }
33339  case DUK_TAG_NULL: {
33340  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
33341  break;
33342  }
33343  case DUK_TAG_BOOLEAN: {
33344  DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
33345  DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
33346  break;
33347  }
33348  case DUK_TAG_STRING: {
33349  duk_hstring *h;
33350  h = DUK_TVAL_GET_STRING(tv);
33351  DUK_ASSERT(h != NULL);
33352  if (DUK_HSTRING_HAS_SYMBOL(h)) {
33353  goto emit_undefined;
33354  }
33355  duk__enc_quote_string(js_ctx, h);
33356  break;
33357  }
33358  case DUK_TAG_OBJECT: {
33359  duk_hobject *obj;
33360  duk_tval *tv_val;
33361  duk_bool_t emitted = 0;
33362  duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
33363  c_func, c_bufobj, c_object, c_abort;
33364 
33365  /* For objects JSON.stringify() only looks for own, enumerable
33366  * properties which is nice for the fast path here.
33367  *
33368  * For arrays JSON.stringify() uses [[Get]] so it will actually
33369  * inherit properties during serialization! This fast path
33370  * supports gappy arrays as long as there's no actual inherited
33371  * property (which might be a getter etc).
33372  *
33373  * Since recursion only happens for objects, we can have both
33374  * recursion and loop checks here. We use a simple, depth-limited
33375  * loop check in the fast path because the object-based tracking
33376  * is very slow (when tested, it accounted for 50% of fast path
33377  * execution time for input data with a lot of small objects!).
33378  */
33379 
33380  /* XXX: for real world code, could just ignore array inheritance
33381  * and only look at array own properties.
33382  */
33383 
33384  /* We rely on a few object flag / class number relationships here,
33385  * assert for them.
33386  */
33387 
33388  obj = DUK_TVAL_GET_OBJECT(tv);
33389  DUK_ASSERT(obj != NULL);
33390  DUK_ASSERT_HOBJECT_VALID(obj);
33391 
33392  /* Once recursion depth is increased, exit path must decrease
33393  * it (though it's OK to abort the fast path).
33394  */
33395 
33396  DUK_ASSERT(js_ctx->recursion_depth >= 0);
33397  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
33398  if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
33399  DUK_DD(DUK_DDPRINT("fast path recursion limit"));
33400  DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
33401  }
33402 
33403  for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
33404  if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
33405  DUK_DD(DUK_DDPRINT("fast path loop detect"));
33406  DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
33407  }
33408  }
33409 
33410  /* Guaranteed by recursion_limit setup so we don't have to
33411  * check twice.
33412  */
33413  DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
33414  js_ctx->visiting[js_ctx->recursion_depth] = obj;
33415  js_ctx->recursion_depth++;
33416 
33417  /* If object has a .toJSON() property, we can't be certain
33418  * that it wouldn't mutate any value arbitrarily, so bail
33419  * out of the fast path.
33420  *
33421  * If an object is a Proxy we also can't avoid side effects
33422  * so abandon.
33423  */
33424  /* XXX: non-callable .toJSON() doesn't need to cause an abort
33425  * but does at the moment, probably not worth fixing.
33426  */
33427  if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
33428  DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
33429  DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
33430  goto abort_fastpath;
33431  }
33432 
33433  /* We could use a switch-case for the class number but it turns out
33434  * a small if-else ladder on class masks is better. The if-ladder
33435  * should be in order of relevancy.
33436  */
33437 
33438  /* XXX: move masks to js_ctx? they don't change during one
33439  * fast path invocation.
33440  */
33441  DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
33442 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33443  if (js_ctx->flag_ext_custom_or_compatible) {
33444  c_all = DUK_HOBJECT_CMASK_ALL;
33445  c_array = DUK_HOBJECT_CMASK_ARRAY;
33446  c_unbox = DUK_HOBJECT_CMASK_NUMBER |
33447  DUK_HOBJECT_CMASK_STRING |
33448  DUK_HOBJECT_CMASK_BOOLEAN |
33449  DUK_HOBJECT_CMASK_POINTER; /* Symbols are not unboxed. */
33450  c_func = DUK_HOBJECT_CMASK_FUNCTION;
33451  c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
33452  c_undef = 0;
33453  c_abort = 0;
33454  c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
33455  }
33456  else
33457 #endif
33458  {
33459  c_all = DUK_HOBJECT_CMASK_ALL;
33460  c_array = DUK_HOBJECT_CMASK_ARRAY;
33461  c_unbox = DUK_HOBJECT_CMASK_NUMBER |
33462  DUK_HOBJECT_CMASK_STRING |
33463  DUK_HOBJECT_CMASK_BOOLEAN; /* Symbols are not unboxed. */
33464  c_func = 0;
33465  c_bufobj = 0;
33466  c_undef = DUK_HOBJECT_CMASK_FUNCTION |
33467  DUK_HOBJECT_CMASK_POINTER;
33468  /* As the fast path doesn't currently properly support
33469  * duk_hbufobj virtual properties, abort fast path if
33470  * we encounter them in plain JSON mode.
33471  */
33472  c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
33473  c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
33474  }
33475 
33476  c_bit = DUK_HOBJECT_GET_CLASS_MASK(obj);
33477  if (c_bit & c_object) {
33478  /* All other object types. */
33479  DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
33480 
33481  /* A non-Array object should not have an array part in practice.
33482  * But since it is supported internally (and perhaps used at some
33483  * point), check and abandon if that's the case.
33484  */
33485  if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
33486  DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
33487  goto abort_fastpath;
33488  }
33489 
33490  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
33491  duk_hstring *k;
33492  duk_size_t prev_size;
33493 
33494  k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
33495  if (!k) {
33496  continue;
33497  }
33498  if (DUK_HSTRING_HAS_ARRIDX(k)) {
33499  /* If an object has array index keys we would need
33500  * to sort them into the ES2015 enumeration order to
33501  * be consistent with the slow path. Abort the fast
33502  * path and handle in the slow path for now.
33503  */
33504  DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
33505  goto abort_fastpath;
33506  }
33507  if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
33508  continue;
33509  }
33510  if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
33511  /* Getter might have arbitrary side effects,
33512  * so bail out.
33513  */
33514  DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
33515  goto abort_fastpath;
33516  }
33517  if (DUK_HSTRING_HAS_SYMBOL(k)) {
33518  continue;
33519  }
33520 
33521  tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
33522 
33523  prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
33524  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
33525  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
33526  duk__enc_key_autoquote(js_ctx, k);
33527  DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
33528  } else {
33529  duk__enc_key_autoquote(js_ctx, k);
33530  DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
33531  }
33532 
33533  if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
33534  DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
33535  DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
33536  } else {
33537  DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
33538  emitted = 1;
33539  }
33540  }
33541 
33542  /* If any non-Array value had enumerable virtual own
33543  * properties, they should be serialized here (actually,
33544  * before the explicit properties). Standard types don't.
33545  */
33546 
33547  if (emitted) {
33548  DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
33549  DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
33550  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
33551  DUK_ASSERT(js_ctx->recursion_depth >= 1);
33552  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
33553  }
33554  }
33555  DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
33556  } else if (c_bit & c_array) {
33557  duk_uint_fast32_t arr_len;
33558  duk_uint_fast32_t asize;
33559 
33560  DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
33561 
33562  /* Assume arrays are dense in the fast path. */
33563  if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
33564  DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
33565  goto abort_fastpath;
33566  }
33567 
33568  arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
33569  asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
33570  /* Array part may be larger than 'length'; if so, iterate
33571  * only up to array 'length'. Array part may also be smaller
33572  * than 'length' in some cases.
33573  */
33574  for (i = 0; i < arr_len; i++) {
33575  duk_tval *tv_arrval;
33576  duk_hstring *h_tmp;
33577  duk_bool_t has_inherited;
33578 
33579  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
33580  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
33581  }
33582 
33583  if (DUK_LIKELY(i < asize)) {
33584  tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
33585  if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
33586  /* Expected case: element is present. */
33587  if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
33588  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
33589  }
33590  goto elem_done;
33591  }
33592  }
33593 
33594  /* Gap in array; check for inherited property,
33595  * bail out if one exists. This should be enough
33596  * to support gappy arrays for all practical code.
33597  */
33598 
33599  h_tmp = duk_push_uint_to_hstring((duk_context *) js_ctx->thr, (duk_uint_t) i);
33600  has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
33601  duk_pop((duk_context *) js_ctx->thr);
33602  if (has_inherited) {
33603  DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
33604  goto abort_fastpath;
33605  }
33606 
33607  /* Ordinary gap, undefined encodes to 'null' in
33608  * standard JSON, but JX/JC use their form for
33609  * undefined to better preserve the typing.
33610  */
33611  DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
33612 #if defined(DUK_USE_JX)
33613  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
33614 #else
33615  DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
33616 #endif
33617  /* fall through */
33618 
33619  elem_done:
33620  DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
33621  emitted = 1;
33622  }
33623 
33624  if (emitted) {
33625  DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
33626  DUK__UNEMIT_1(js_ctx); /* eat trailing comma */
33627  if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
33628  DUK_ASSERT(js_ctx->recursion_depth >= 1);
33629  duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1);
33630  }
33631  }
33632  DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
33633  } else if (c_bit & c_unbox) {
33634  /* Certain boxed types are required to go through
33635  * automatic unboxing. Rely on internal value being
33636  * sane (to avoid infinite recursion).
33637  */
33638  DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0); /* Symbols are not unboxed. */
33639 
33640 #if 1
33641  /* The code below is incorrect if .toString() or .valueOf() have
33642  * have been overridden. The correct approach would be to look up
33643  * the method(s) and if they resolve to the built-in function we
33644  * can safely bypass it and look up the internal value directly.
33645  * Unimplemented for now, abort fast path for boxed values.
33646  */
33647  goto abort_fastpath;
33648 #else /* disabled */
33649  /* Disabled until fixed, see above. */
33650  duk_tval *tv_internal;
33651 
33652  DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
33653 
33654  tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
33655  DUK_ASSERT(tv_internal != NULL);
33656  DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
33657  DUK_TVAL_IS_NUMBER(tv_internal) ||
33658  DUK_TVAL_IS_BOOLEAN(tv_internal) ||
33659  DUK_TVAL_IS_POINTER(tv_internal));
33660 
33661  tv = tv_internal;
33662  DUK_ASSERT(js_ctx->recursion_depth > 0);
33663  js_ctx->recursion_depth--; /* required to keep recursion depth correct */
33664  goto restart_match;
33665 #endif /* disabled */
33666 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33667  } else if (c_bit & c_func) {
33668  DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
33669 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
33670  } else if (c_bit & c_bufobj) {
33671  duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
33672 #endif
33673 #endif
33674  } else if (c_bit & c_abort) {
33675  DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
33676  goto abort_fastpath;
33677  } else {
33678  DUK_ASSERT((c_bit & c_undef) != 0);
33679 
33680  /* Must decrease recursion depth before returning. */
33681  DUK_ASSERT(js_ctx->recursion_depth > 0);
33682  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
33683  js_ctx->recursion_depth--;
33684  goto emit_undefined;
33685  }
33686 
33687  DUK_ASSERT(js_ctx->recursion_depth > 0);
33688  DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
33689  js_ctx->recursion_depth--;
33690  break;
33691  }
33692  case DUK_TAG_BUFFER: {
33693  /* Plain buffers are treated like Uint8Arrays: they have
33694  * enumerable indices. Other virtual properties are not
33695  * enumerable, and inherited properties are not serialized.
33696  * However, there can be a replacer (not relevant here) or
33697  * a .toJSON() method (which we need to check for explicitly).
33698  */
33699 
33700 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
33701  if (duk_hobject_hasprop_raw(js_ctx->thr,
33702  js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
33703  DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
33704  DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
33705  goto abort_fastpath;
33706  }
33707 #endif
33708 
33709 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33710  if (js_ctx->flag_ext_custom_or_compatible) {
33711  duk__enc_buffer(js_ctx, DUK_TVAL_GET_BUFFER(tv));
33712  break;
33713  }
33714 #endif
33715  /* Could implement a fast path, but abort fast path for now. */
33716  DUK_DD(DUK_DDPRINT("value is a plain buffer and serializing as plain JSON, abort fast path"));
33717  goto abort_fastpath;
33718  }
33719  case DUK_TAG_POINTER: {
33720 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33721  if (js_ctx->flag_ext_custom_or_compatible) {
33722  duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
33723  break;
33724  } else {
33725  goto emit_undefined;
33726  }
33727 #else
33728  goto emit_undefined;
33729 #endif
33730  }
33731  case DUK_TAG_LIGHTFUNC: {
33732  /* A lightfunc might also inherit a .toJSON() so just bail out. */
33733  /* XXX: Could just lookup .toJSON() and continue in fast path,
33734  * as it would almost never be defined.
33735  */
33736  DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
33737  goto abort_fastpath;
33738  }
33739 #if defined(DUK_USE_FASTINT)
33740  case DUK_TAG_FASTINT: {
33741  /* Number serialization has a significant impact relative to
33742  * other fast path code, so careful fast path for fastints.
33743  */
33744  duk__enc_fastint_tval(js_ctx, tv);
33745  break;
33746  }
33747 #endif
33748  default: {
33749  /* XXX: A fast path for usual integers would be useful when
33750  * fastint support is not enabled.
33751  */
33752  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
33753  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
33754 
33755  /* XXX: Stack discipline is annoying, could be changed in numconv. */
33756  duk_push_tval((duk_context *) js_ctx->thr, tv);
33757  duk__enc_double(js_ctx);
33758  duk_pop((duk_context *) js_ctx->thr);
33759 
33760 #if 0
33761  /* Could also rely on native sprintf(), but it will handle
33762  * values like NaN, Infinity, -0, exponent notation etc in
33763  * a JSON-incompatible way.
33764  */
33765  duk_double_t d;
33766  char buf[64];
33767 
33768  DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
33769  d = DUK_TVAL_GET_DOUBLE(tv);
33770  DUK_SPRINTF(buf, "%lg", d);
33771  DUK__EMIT_CSTR(js_ctx, buf);
33772 #endif
33773  }
33774  }
33775  return 1; /* not undefined */
33776 
33777  emit_undefined:
33778  return 0; /* value was undefined/unsupported */
33779 
33780  abort_fastpath:
33781  /* Error message doesn't matter: the error is ignored anyway. */
33782  DUK_DD(DUK_DDPRINT("aborting fast path"));
33783  DUK_ERROR_INTERNAL(js_ctx->thr);
33784  return 0; /* unreachable */
33785 }
33786 
33787 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_context *ctx, void *udata) {
33788  duk_json_enc_ctx *js_ctx;
33789  duk_tval *tv;
33790 
33791  DUK_ASSERT(ctx != NULL);
33792  DUK_ASSERT(udata != NULL);
33793 
33794  js_ctx = (duk_json_enc_ctx *) udata;
33795  DUK_ASSERT(js_ctx != NULL);
33796 
33797  tv = DUK_GET_TVAL_NEGIDX(ctx, -1);
33798  if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
33799  DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
33800  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx); /* Error message is ignored, so doesn't matter. */
33801  }
33802 
33803  return 0;
33804 }
33805 #endif /* DUK_USE_JSON_STRINGIFY_FASTPATH */
33806 
33807 /*
33808  * Top level wrappers
33809  */
33810 
33811 DUK_INTERNAL
33812 void duk_bi_json_parse_helper(duk_context *ctx,
33813  duk_idx_t idx_value,
33814  duk_idx_t idx_reviver,
33815  duk_small_uint_t flags) {
33816  duk_hthread *thr = (duk_hthread *) ctx;
33817  duk_json_dec_ctx js_ctx_alloc;
33818  duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
33819  duk_hstring *h_text;
33820 #if defined(DUK_USE_ASSERTIONS)
33821  duk_idx_t entry_top = duk_get_top(ctx);
33822 #endif
33823 
33824  /* negative top-relative indices not allowed now */
33825  DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
33826  DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
33827 
33828  DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
33829  (duk_tval *) duk_get_tval(ctx, idx_value),
33830  (duk_tval *) duk_get_tval(ctx, idx_reviver),
33831  (unsigned long) flags,
33832  (long) duk_get_top(ctx)));
33833 
33834  DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
33835  js_ctx->thr = thr;
33836 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
33837  /* nothing now */
33838 #endif
33839  js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
33840  DUK_ASSERT(js_ctx->recursion_depth == 0);
33841 
33842  /* Flag handling currently assumes that flags are consistent. This is OK
33843  * because the call sites are now strictly controlled.
33844  */
33845 
33846  js_ctx->flags = flags;
33847 #if defined(DUK_USE_JX)
33848  js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
33849 #endif
33850 #if defined(DUK_USE_JC)
33851  js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
33852 #endif
33853 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33854  js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
33855 #endif
33856 
33857  h_text = duk_to_hstring(ctx, idx_value); /* coerce in-place; rejects Symbols */
33858  DUK_ASSERT(h_text != NULL);
33859 
33860  /* JSON parsing code is allowed to read [p_start,p_end]: p_end is
33861  * valid and points to the string NUL terminator (which is always
33862  * guaranteed for duk_hstrings.
33863  */
33864  js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
33865  js_ctx->p = js_ctx->p_start;
33866  js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
33867  DUK_HSTRING_GET_BYTELEN(h_text);
33868  DUK_ASSERT(*(js_ctx->p_end) == 0x00);
33869 
33870  duk__dec_value(js_ctx); /* -> [ ... value ] */
33871 
33872  /* Trailing whitespace has been eaten by duk__dec_value(), so if
33873  * we're not at end of input here, it's a SyntaxError.
33874  */
33875 
33876  if (js_ctx->p != js_ctx->p_end) {
33877  duk__dec_syntax_error(js_ctx);
33878  }
33879 
33880  if (duk_is_callable(ctx, idx_reviver)) {
33881  DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
33882  (duk_tval *) duk_get_tval(ctx, idx_reviver)));
33883 
33884  js_ctx->idx_reviver = idx_reviver;
33885 
33886  duk_push_object(ctx);
33887  duk_dup_m2(ctx); /* -> [ ... val root val ] */
33888  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_EMPTY_STRING); /* default attrs ok */
33889  duk_push_hstring_stridx(ctx, DUK_STRIDX_EMPTY_STRING); /* -> [ ... val root "" ] */
33890 
33891  DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
33892  (duk_tval *) duk_get_tval(ctx, -2),
33893  (duk_tval *) duk_get_tval(ctx, -1)));
33894 
33895  duk__dec_reviver_walk(js_ctx); /* [ ... val root "" ] -> [ ... val val' ] */
33896  duk_remove_m2(ctx); /* -> [ ... val' ] */
33897  } else {
33898  DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
33899  (duk_tval *) duk_get_tval(ctx, idx_reviver)));
33900  }
33901 
33902  /* Final result is at stack top. */
33903 
33904  DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
33905  (duk_tval *) duk_get_tval(ctx, idx_value),
33906  (duk_tval *) duk_get_tval(ctx, idx_reviver),
33907  (unsigned long) flags,
33908  (duk_tval *) duk_get_tval(ctx, -1),
33909  (long) duk_get_top(ctx)));
33910 
33911  DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
33912 }
33913 
33914 DUK_INTERNAL
33915 void duk_bi_json_stringify_helper(duk_context *ctx,
33916  duk_idx_t idx_value,
33917  duk_idx_t idx_replacer,
33918  duk_idx_t idx_space,
33919  duk_small_uint_t flags) {
33920  duk_hthread *thr = (duk_hthread *) ctx;
33921  duk_json_enc_ctx js_ctx_alloc;
33922  duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
33923  duk_hobject *h;
33924  duk_idx_t idx_holder;
33925  duk_idx_t entry_top;
33926 
33927  /* negative top-relative indices not allowed now */
33928  DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
33929  DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
33930  DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
33931 
33932  DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
33933  (duk_tval *) duk_get_tval(ctx, idx_value),
33934  (duk_tval *) duk_get_tval(ctx, idx_replacer),
33935  (duk_tval *) duk_get_tval(ctx, idx_space),
33936  (unsigned long) flags,
33937  (long) duk_get_top(ctx)));
33938 
33939  entry_top = duk_get_top(ctx);
33940 
33941  /*
33942  * Context init
33943  */
33944 
33945  DUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));
33946  js_ctx->thr = thr;
33947 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
33948  js_ctx->h_replacer = NULL;
33949  js_ctx->h_gap = NULL;
33950 #endif
33951  js_ctx->idx_proplist = -1;
33952 
33953  /* Flag handling currently assumes that flags are consistent. This is OK
33954  * because the call sites are now strictly controlled.
33955  */
33956 
33957  js_ctx->flags = flags;
33958  js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
33959  js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
33960 #if defined(DUK_USE_JX)
33961  js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
33962 #endif
33963 #if defined(DUK_USE_JC)
33964  js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
33965 #endif
33966 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33967  js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
33968 #endif
33969 
33970  /* The #if defined() clutter here handles the JX/JC enable/disable
33971  * combinations properly.
33972  */
33973 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
33974  js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL; /* standard JSON; array gaps */
33975 #if defined(DUK_USE_JX)
33976  if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
33977  js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
33978  js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
33979  js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
33980  js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
33981  js_ctx->stridx_custom_function =
33982  (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
33983  DUK_STRIDX_JSON_EXT_FUNCTION2 :
33984  DUK_STRIDX_JSON_EXT_FUNCTION1;
33985  }
33986 #endif /* DUK_USE_JX */
33987 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
33988  else
33989 #endif /* DUK_USE_JX && DUK_USE_JC */
33990 #if defined(DUK_USE_JC)
33991  if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
33992  js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
33993  js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
33994  js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
33995  js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
33996  js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
33997  }
33998 #endif /* DUK_USE_JC */
33999 #endif /* DUK_USE_JX || DUK_USE_JC */
34000 
34001 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
34002  if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
34003  DUK_JSON_FLAG_EXT_COMPATIBLE)) {
34004  DUK_ASSERT(js_ctx->mask_for_undefined == 0); /* already zero */
34005  }
34006  else
34007 #endif /* DUK_USE_JX || DUK_USE_JC */
34008  {
34009  /* Plain buffer is treated like ArrayBuffer and serialized.
34010  * Lightfuncs are treated like objects, but JSON explicitly
34011  * skips serializing Function objects so we can just reject
34012  * lightfuncs here.
34013  */
34014  js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
34015  DUK_TYPE_MASK_POINTER |
34016  DUK_TYPE_MASK_LIGHTFUNC;
34017  }
34018 
34019  DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
34020 
34021  js_ctx->idx_loop = duk_push_bare_object(ctx);
34022  DUK_ASSERT(js_ctx->idx_loop >= 0);
34023 
34024  /* [ ... buf loop ] */
34025 
34026  /*
34027  * Process replacer/proplist (2nd argument to JSON.stringify)
34028  */
34029 
34030  h = duk_get_hobject(ctx, idx_replacer);
34031  if (h != NULL) {
34032  if (DUK_HOBJECT_IS_CALLABLE(h)) {
34033  js_ctx->h_replacer = h;
34034  } else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
34035  /* Here the specification requires correct array index enumeration
34036  * which is a bit tricky for sparse arrays (it is handled by the
34037  * enum setup code). We now enumerate ancestors too, although the
34038  * specification is not very clear on whether that is required.
34039  */
34040 
34041  duk_uarridx_t plist_idx = 0;
34042  duk_small_uint_t enum_flags;
34043 
34044  js_ctx->idx_proplist = duk_push_array(ctx); /* XXX: array internal? */
34045 
34046  enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
34047  DUK_ENUM_SORT_ARRAY_INDICES; /* expensive flag */
34048  duk_enum(ctx, idx_replacer, enum_flags);
34049  while (duk_next(ctx, -1 /*enum_index*/, 1 /*get_value*/)) {
34050  /* [ ... proplist enum_obj key val ] */
34051  if (duk__enc_allow_into_proplist(duk_get_tval(ctx, -1))) {
34052  /* XXX: duplicates should be eliminated here */
34053  DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
34054  (duk_tval *) duk_get_tval(ctx, -2),
34055  (duk_tval *) duk_get_tval(ctx, -1)));
34056  duk_to_string(ctx, -1); /* extra coercion of strings is OK */
34057  duk_put_prop_index(ctx, -4, plist_idx); /* -> [ ... proplist enum_obj key ] */
34058  plist_idx++;
34059  duk_pop(ctx);
34060  } else {
34061  DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
34062  (duk_tval *) duk_get_tval(ctx, -2),
34063  (duk_tval *) duk_get_tval(ctx, -1)));
34064  duk_pop_2(ctx);
34065  }
34066  }
34067  duk_pop(ctx); /* pop enum */
34068 
34069  /* [ ... proplist ] */
34070  }
34071  }
34072 
34073  /* [ ... buf loop (proplist) ] */
34074 
34075  /*
34076  * Process space (3rd argument to JSON.stringify)
34077  */
34078 
34079  h = duk_get_hobject(ctx, idx_space);
34080  if (h != NULL) {
34081  int c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
34082  if (c == DUK_HOBJECT_CLASS_NUMBER) {
34083  duk_to_number(ctx, idx_space);
34084  } else if (c == DUK_HOBJECT_CLASS_STRING) {
34085  duk_to_string(ctx, idx_space);
34086  }
34087  }
34088 
34089  if (duk_is_number(ctx, idx_space)) {
34090  duk_small_int_t nspace;
34091  /* spaces[] must be static to allow initializer with old compilers like BCC */
34092  static const char spaces[10] = {
34093  DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
34094  DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
34095  DUK_ASC_SPACE, DUK_ASC_SPACE
34096  }; /* XXX: helper */
34097 
34098  /* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
34099  nspace = (duk_small_int_t) duk_to_int_clamped(ctx, idx_space, 0 /*minval*/, 10 /*maxval*/);
34100  DUK_ASSERT(nspace >= 0 && nspace <= 10);
34101 
34102  duk_push_lstring(ctx, spaces, (duk_size_t) nspace);
34103  js_ctx->h_gap = duk_known_hstring(ctx, -1);
34104  DUK_ASSERT(js_ctx->h_gap != NULL);
34105  } else if (duk_is_string_notsymbol(ctx, idx_space)) {
34106  duk_dup(ctx, idx_space);
34107  duk_substring(ctx, -1, 0, 10); /* clamp to 10 chars */
34108  js_ctx->h_gap = duk_known_hstring(ctx, -1);
34109  } else {
34110  /* nop */
34111  }
34112 
34113  if (js_ctx->h_gap != NULL) {
34114  /* if gap is empty, behave as if not given at all */
34115  if (DUK_HSTRING_GET_CHARLEN(js_ctx->h_gap) == 0) {
34116  js_ctx->h_gap = NULL;
34117  }
34118  }
34119 
34120  /* [ ... buf loop (proplist) (gap) ] */
34121 
34122  /*
34123  * Fast path: assume no mutation, iterate object property tables
34124  * directly; bail out if that assumption doesn't hold.
34125  */
34126 
34127 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
34128  if (js_ctx->h_replacer == NULL && /* replacer is a mutation risk */
34129  js_ctx->idx_proplist == -1) { /* proplist is very rare */
34130  duk_int_t pcall_rc;
34131  duk_small_uint_t prev_mark_and_sweep_base_flags;
34132 
34133  DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
34134 
34135  /* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
34136  * array so we don't need two counter checks in the fast path. The
34137  * slow path has a much larger recursion limit which we'll use if
34138  * necessary.
34139  */
34140  DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
34141  js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
34142  DUK_ASSERT(js_ctx->recursion_depth == 0);
34143 
34144  /* Execute the fast path in a protected call. If any error is thrown,
34145  * fall back to the slow path. This includes e.g. recursion limit
34146  * because the fast path has a smaller recursion limit (and simpler,
34147  * limited loop detection).
34148  */
34149 
34150  duk_dup(ctx, idx_value);
34151 
34152  /* Must prevent finalizers which may have arbitrary side effects. */
34153  prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
34154  thr->heap->mark_and_sweep_base_flags |=
34155  DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
34156  DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact any objects */
34157 
34158  pcall_rc = duk_safe_call(ctx, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
34159 
34160  thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
34161 
34162  if (pcall_rc == DUK_EXEC_SUCCESS) {
34163  DUK_DD(DUK_DDPRINT("fast path successful"));
34164  DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
34165  goto replace_finished;
34166  }
34167 
34168  /* We come here for actual aborts (like encountering .toJSON())
34169  * but also for recursion/loop errors. Bufwriter size can be
34170  * kept because we'll probably need at least as much as we've
34171  * allocated so far.
34172  */
34173  DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
34174  DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
34175  js_ctx->recursion_depth = 0;
34176  }
34177 #endif
34178 
34179  /*
34180  * Create wrapper object and serialize
34181  */
34182 
34183  idx_holder = duk_push_object(ctx);
34184  duk_dup(ctx, idx_value);
34185  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_EMPTY_STRING);
34186 
34187  DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
34188  "proplist=%!T, gap=%!O, holder=%!T",
34189  (unsigned long) js_ctx->flags,
34190  (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
34191  (duk_heaphdr *) js_ctx->h_replacer,
34192  (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
34193  (duk_heaphdr *) js_ctx->h_gap,
34194  (duk_tval *) duk_get_tval(ctx, -1)));
34195 
34196  /* serialize the wrapper with empty string key */
34197 
34198  duk_push_hstring_empty(ctx);
34199 
34200  /* [ ... buf loop (proplist) (gap) holder "" ] */
34201 
34202  js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
34203  DUK_ASSERT(js_ctx->recursion_depth == 0);
34204 
34205  if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) { /* [ ... holder key ] -> [ ... holder ] */
34206  /* Result is undefined. */
34207  duk_push_undefined(ctx);
34208  } else {
34209  /* Convert buffer to result string. */
34210  DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
34211  }
34212 
34213  DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
34214  "proplist=%!T, gap=%!O, holder=%!T",
34215  (unsigned long) js_ctx->flags,
34216  (duk_tval *) duk_get_tval(ctx, js_ctx->idx_loop),
34217  (duk_heaphdr *) js_ctx->h_replacer,
34218  (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(ctx, js_ctx->idx_proplist) : NULL),
34219  (duk_heaphdr *) js_ctx->h_gap,
34220  (duk_tval *) duk_get_tval(ctx, idx_holder)));
34221 
34222  /* The stack has a variable shape here, so force it to the
34223  * desired one explicitly.
34224  */
34225 
34226 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
34227  replace_finished:
34228 #endif
34229  duk_replace(ctx, entry_top);
34230  duk_set_top(ctx, entry_top + 1);
34231 
34232  DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
34233  "flags=0x%08lx, result=%!T, stack_top=%ld",
34234  (duk_tval *) duk_get_tval(ctx, idx_value),
34235  (duk_tval *) duk_get_tval(ctx, idx_replacer),
34236  (duk_tval *) duk_get_tval(ctx, idx_space),
34237  (unsigned long) flags,
34238  (duk_tval *) duk_get_tval(ctx, -1),
34239  (long) duk_get_top(ctx)));
34240 
34241  DUK_ASSERT(duk_get_top(ctx) == entry_top + 1);
34242 }
34243 
34244 #if defined(DUK_USE_JSON_BUILTIN)
34245 
34246 /*
34247  * Entry points
34248  */
34249 
34250 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_context *ctx) {
34251  duk_bi_json_parse_helper(ctx,
34252  0 /*idx_value*/,
34253  1 /*idx_replacer*/,
34254  0 /*flags*/);
34255  return 1;
34256 }
34257 
34258 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx) {
34259  duk_bi_json_stringify_helper(ctx,
34260  0 /*idx_value*/,
34261  1 /*idx_replacer*/,
34262  2 /*idx_space*/,
34263  0 /*flags*/);
34264  return 1;
34265 }
34266 
34267 #endif /* DUK_USE_JSON_BUILTIN */
34268 
34269 #endif /* DUK_USE_JSON_SUPPORT */
34270 
34271 /* automatic undefs */
34272 #undef DUK__EMIT_1
34273 #undef DUK__EMIT_2
34274 #undef DUK__EMIT_CSTR
34275 #undef DUK__EMIT_HSTR
34276 #undef DUK__EMIT_STRIDX
34277 #undef DUK__JSON_DECSTR_BUFSIZE
34278 #undef DUK__JSON_DECSTR_CHUNKSIZE
34279 #undef DUK__JSON_ENCSTR_CHUNKSIZE
34280 #undef DUK__JSON_MAX_ESC_LEN
34281 #undef DUK__JSON_STRINGIFY_BUFSIZE
34282 #undef DUK__MKESC
34283 #undef DUK__UNEMIT_1
34284 /*
34285  * Math built-ins
34286  */
34287 
34288 /* #include duk_internal.h -> already included */
34289 
34290 #if defined(DUK_USE_MATH_BUILTIN)
34291 
34292 /*
34293  * Use static helpers which can work with math.h functions matching
34294  * the following signatures. This is not portable if any of these math
34295  * functions is actually a macro.
34296  *
34297  * Typing here is intentionally 'double' wherever values interact with
34298  * the standard library APIs.
34299  */
34300 
34301 typedef double (*duk__one_arg_func)(double);
34302 typedef double (*duk__two_arg_func)(double, double);
34303 
34304 DUK_LOCAL duk_ret_t duk__math_minmax(duk_context *ctx, duk_double_t initial, duk__two_arg_func min_max) {
34305  duk_idx_t n = duk_get_top(ctx);
34306  duk_idx_t i;
34307  duk_double_t res = initial;
34308  duk_double_t t;
34309 
34310  /*
34311  * Note: fmax() does not match the E5 semantics. E5 requires
34312  * that if -any- input to Math.max() is a NaN, the result is a
34313  * NaN. fmax() will return a NaN only if -both- inputs are NaN.
34314  * Same applies to fmin().
34315  *
34316  * Note: every input value must be coerced with ToNumber(), even
34317  * if we know the result will be a NaN anyway: ToNumber() may have
34318  * side effects for which even order of evaluation matters.
34319  */
34320 
34321  for (i = 0; i < n; i++) {
34322  t = duk_to_number(ctx, i);
34323  if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
34324  /* Note: not normalized, but duk_push_number() will normalize */
34325  res = (duk_double_t) DUK_DOUBLE_NAN;
34326  } else {
34327  res = (duk_double_t) min_max(res, (double) t);
34328  }
34329  }
34330 
34331  duk_push_number(ctx, res);
34332  return 1;
34333 }
34334 
34335 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
34336  /* fmin() with args -0 and +0 is not guaranteed to return
34337  * -0 as Ecmascript requires.
34338  */
34339  if (x == 0 && y == 0) {
34340  duk_double_union du1, du2;
34341  du1.d = x;
34342  du2.d = y;
34343 
34344  /* Already checked to be zero so these must hold, and allow us
34345  * to check for "x is -0 or y is -0" by ORing the high parts
34346  * for comparison.
34347  */
34348  DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
34349  DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
34350 
34351  /* XXX: what's the safest way of creating a negative zero? */
34352  if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
34353  /* Enter here if either x or y (or both) is -0. */
34354  return -0.0;
34355  } else {
34356  return +0.0;
34357  }
34358  }
34359  return duk_double_fmin(x, y);
34360 }
34361 
34362 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
34363  /* fmax() with args -0 and +0 is not guaranteed to return
34364  * +0 as Ecmascript requires.
34365  */
34366  if (x == 0 && y == 0) {
34367  if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
34368  return +0.0;
34369  } else {
34370  return -0.0;
34371  }
34372  }
34373  return duk_double_fmax(x, y);
34374 }
34375 
34376 #if defined(DUK_USE_ES6)
34377 DUK_LOCAL double duk__cbrt(double x) {
34378  /* cbrt() is C99. To avoid hassling embedders with the need to provide a
34379  * cube root function, we can get by with pow(). The result is not
34380  * identical, but that's OK: ES2015 says it's implementation-dependent.
34381  */
34382 
34383 #if defined(DUK_CBRT)
34384  /* cbrt() matches ES2015 requirements. */
34385  return DUK_CBRT(x);
34386 #else
34387  duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
34388 
34389  /* pow() does not, however. */
34390  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
34391  return x;
34392  }
34393  if (DUK_SIGNBIT(x)) {
34394  return -DUK_POW(-x, 1.0 / 3.0);
34395  } else {
34396  return DUK_POW(x, 1.0 / 3.0);
34397  }
34398 #endif
34399 }
34400 
34401 DUK_LOCAL double duk__log2(double x) {
34402 #if defined(DUK_LOG2)
34403  return DUK_LOG2(x);
34404 #else
34405  return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
34406 #endif
34407 }
34408 
34409 DUK_LOCAL double duk__log10(double x) {
34410 #if defined(DUK_LOG10)
34411  return DUK_LOG10(x);
34412 #else
34413  return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
34414 #endif
34415 }
34416 
34417 DUK_LOCAL double duk__trunc(double x) {
34418 #if defined(DUK_TRUNC)
34419  return DUK_TRUNC(x);
34420 #else
34421  /* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
34422  * is required to return -0 when the argument is -0.
34423  */
34424  return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
34425 #endif
34426 }
34427 #endif /* DUK_USE_ES6 */
34428 
34429 DUK_LOCAL double duk__round_fixed(double x) {
34430  /* Numbers half-way between integers must be rounded towards +Infinity,
34431  * e.g. -3.5 must be rounded to -3 (not -4). When rounded to zero, zero
34432  * sign must be set appropriately. E5.1 Section 15.8.2.15.
34433  *
34434  * Note that ANSI C round() is "round to nearest integer, away from zero",
34435  * which is incorrect for negative values. Here we make do with floor().
34436  */
34437 
34438  duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
34439  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
34440  return x;
34441  }
34442 
34443  /*
34444  * x is finite and non-zero
34445  *
34446  * -1.6 -> floor(-1.1) -> -2
34447  * -1.5 -> floor(-1.0) -> -1 (towards +Inf)
34448  * -1.4 -> floor(-0.9) -> -1
34449  * -0.5 -> -0.0 (special case)
34450  * -0.1 -> -0.0 (special case)
34451  * +0.1 -> +0.0 (special case)
34452  * +0.5 -> floor(+1.0) -> 1 (towards +Inf)
34453  * +1.4 -> floor(+1.9) -> 1
34454  * +1.5 -> floor(+2.0) -> 2 (towards +Inf)
34455  * +1.6 -> floor(+2.1) -> 2
34456  */
34457 
34458  if (x >= -0.5 && x < 0.5) {
34459  /* +0.5 is handled by floor, this is on purpose */
34460  if (x < 0.0) {
34461  return -0.0;
34462  } else {
34463  return +0.0;
34464  }
34465  }
34466 
34467  return DUK_FLOOR(x + 0.5);
34468 }
34469 
34470 /* Wrappers for calling standard math library methods. These may be required
34471  * on platforms where one or more of the math built-ins are defined as macros
34472  * or inline functions and are thus not suitable to be used as function pointers.
34473  */
34474 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
34475 DUK_LOCAL double duk__fabs(double x) {
34476  return DUK_FABS(x);
34477 }
34478 DUK_LOCAL double duk__acos(double x) {
34479  return DUK_ACOS(x);
34480 }
34481 DUK_LOCAL double duk__asin(double x) {
34482  return DUK_ASIN(x);
34483 }
34484 DUK_LOCAL double duk__atan(double x) {
34485  return DUK_ATAN(x);
34486 }
34487 DUK_LOCAL double duk__ceil(double x) {
34488  return DUK_CEIL(x);
34489 }
34490 DUK_LOCAL double duk__cos(double x) {
34491  return DUK_COS(x);
34492 }
34493 DUK_LOCAL double duk__exp(double x) {
34494  return DUK_EXP(x);
34495 }
34496 DUK_LOCAL double duk__floor(double x) {
34497  return DUK_FLOOR(x);
34498 }
34499 DUK_LOCAL double duk__log(double x) {
34500  return DUK_LOG(x);
34501 }
34502 DUK_LOCAL double duk__sin(double x) {
34503  return DUK_SIN(x);
34504 }
34505 DUK_LOCAL double duk__sqrt(double x) {
34506  return DUK_SQRT(x);
34507 }
34508 DUK_LOCAL double duk__tan(double x) {
34509  return DUK_TAN(x);
34510 }
34511 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
34512 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
34513  /* Specific fixes to common atan2() implementation issues:
34514  * - test-bug-mingw-math-issues.js
34515  */
34516  if (DUK_ISINF(x) && DUK_ISINF(y)) {
34517  if (DUK_SIGNBIT(x)) {
34518  if (DUK_SIGNBIT(y)) {
34519  return -2.356194490192345;
34520  } else {
34521  return -0.7853981633974483;
34522  }
34523  } else {
34524  if (DUK_SIGNBIT(y)) {
34525  return 2.356194490192345;
34526  } else {
34527  return 0.7853981633974483;
34528  }
34529  }
34530  }
34531 #else
34532  /* Some ISO C assumptions. */
34533  DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
34534  DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
34535  DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
34536  DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
34537 #endif
34538 
34539  return DUK_ATAN2(x, y);
34540 }
34541 #endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
34542 
34543 /* order must match constants in genbuiltins.py */
34544 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
34545 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
34546  duk__fabs,
34547  duk__acos,
34548  duk__asin,
34549  duk__atan,
34550  duk__ceil,
34551  duk__cos,
34552  duk__exp,
34553  duk__floor,
34554  duk__log,
34555  duk__round_fixed,
34556  duk__sin,
34557  duk__sqrt,
34558  duk__tan,
34559 #if defined(DUK_USE_ES6)
34560  duk__cbrt,
34561  duk__log2,
34562  duk__log10,
34563  duk__trunc
34564 #endif
34565 #else /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
34566  DUK_FABS,
34567  DUK_ACOS,
34568  DUK_ASIN,
34569  DUK_ATAN,
34570  DUK_CEIL,
34571  DUK_COS,
34572  DUK_EXP,
34573  DUK_FLOOR,
34574  DUK_LOG,
34575  duk__round_fixed,
34576  DUK_SIN,
34577  DUK_SQRT,
34578  DUK_TAN,
34579 #if defined(DUK_USE_ES6)
34580  duk__cbrt,
34581  duk__log2,
34582  duk__log10,
34583  duk__trunc
34584 #endif
34585 #endif /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
34586 };
34587 
34588 /* order must match constants in genbuiltins.py */
34589 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
34590 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
34591  duk__atan2_fixed,
34592  duk_js_arith_pow
34593 #else
34594  duk__atan2_fixed,
34595  duk_js_arith_pow
34596 #endif
34597 };
34598 
34599 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx) {
34600  duk_small_int_t fun_idx = duk_get_current_magic(ctx);
34601  duk__one_arg_func fun;
34602  duk_double_t arg1;
34603 
34604  DUK_ASSERT(fun_idx >= 0);
34605  DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
34606  arg1 = duk_to_number(ctx, 0);
34607  fun = duk__one_arg_funcs[fun_idx];
34608  duk_push_number(ctx, (duk_double_t) fun((double) arg1));
34609  return 1;
34610 }
34611 
34612 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx) {
34613  duk_small_int_t fun_idx = duk_get_current_magic(ctx);
34614  duk__two_arg_func fun;
34615  duk_double_t arg1;
34616  duk_double_t arg2;
34617 
34618  DUK_ASSERT(fun_idx >= 0);
34619  DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
34620  arg1 = duk_to_number(ctx, 0); /* explicit ordered evaluation to match coercion semantics */
34621  arg2 = duk_to_number(ctx, 1);
34622  fun = duk__two_arg_funcs[fun_idx];
34623  duk_push_number(ctx, (duk_double_t) fun((double) arg1, (double) arg2));
34624  return 1;
34625 }
34626 
34627 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_context *ctx) {
34628  return duk__math_minmax(ctx, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
34629 }
34630 
34631 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_context *ctx) {
34632  return duk__math_minmax(ctx, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
34633 }
34634 
34635 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_context *ctx) {
34636  duk_push_number(ctx, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE((duk_hthread *) ctx));
34637  return 1;
34638 }
34639 
34640 #if defined(DUK_USE_ES6)
34641 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx) {
34642  /*
34643  * E6 Section 20.2.2.18: Math.hypot
34644  *
34645  * - If no arguments are passed, the result is +0.
34646  * - If any argument is +inf, the result is +inf.
34647  * - If any argument is -inf, the result is +inf.
34648  * - If no argument is +inf or -inf, and any argument is NaN, the result is
34649  * NaN.
34650  * - If all arguments are either +0 or -0, the result is +0.
34651  */
34652 
34653  duk_idx_t nargs;
34654  duk_idx_t i;
34655  duk_bool_t found_nan;
34656  duk_double_t max;
34657  duk_double_t sum, summand;
34658  duk_double_t comp, prelim;
34659  duk_double_t t;
34660 
34661  nargs = duk_get_top(ctx);
34662 
34663  /* Find the highest value. Also ToNumber() coerces. */
34664  max = 0.0;
34665  found_nan = 0;
34666  for (i = 0; i < nargs; i++) {
34667  t = DUK_FABS(duk_to_number(ctx, i));
34668  if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
34669  found_nan = 1;
34670  } else {
34671  max = duk_double_fmax(max, t);
34672  }
34673  }
34674 
34675  /* Early return cases. */
34676  if (max == DUK_DOUBLE_INFINITY) {
34677  duk_push_number(ctx, DUK_DOUBLE_INFINITY);
34678  return 1;
34679  } else if (found_nan) {
34680  duk_push_number(ctx, DUK_DOUBLE_NAN);
34681  return 1;
34682  } else if (max == 0.0) {
34683  duk_push_number(ctx, 0.0);
34684  /* Otherwise we'd divide by zero. */
34685  return 1;
34686  }
34687 
34688  /* Use Kahan summation and normalize to the highest value to minimize
34689  * floating point rounding error and avoid overflow.
34690  *
34691  * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
34692  */
34693  sum = 0.0;
34694  comp = 0.0;
34695  for (i = 0; i < nargs; i++) {
34696  t = DUK_FABS(duk_get_number(ctx, i)) / max;
34697  summand = (t * t) - comp;
34698  prelim = sum + summand;
34699  comp = (prelim - sum) - summand;
34700  sum = prelim;
34701  }
34702 
34703  duk_push_number(ctx, (duk_double_t) DUK_SQRT(sum) * max);
34704  return 1;
34705 }
34706 #endif /* DUK_USE_ES6 */
34707 
34708 #endif /* DUK_USE_MATH_BUILTIN */
34709 /*
34710  * Number built-ins
34711  */
34712 
34713 /* #include duk_internal.h -> already included */
34714 
34715 #if defined(DUK_USE_NUMBER_BUILTIN)
34716 
34717 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_context *ctx) {
34718  duk_hobject *h;
34719 
34720  /* Number built-in accepts a plain number or a Number object (whose
34721  * internal value is operated on). Other types cause TypeError.
34722  */
34723 
34724  duk_push_this(ctx);
34725  if (duk_is_number(ctx, -1)) {
34726  DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
34727  goto done;
34728  }
34729  h = duk_get_hobject(ctx, -1);
34730  if (!h ||
34731  (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
34732  DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
34733  DUK_ERROR_TYPE((duk_hthread *) ctx, "number expected");
34734  }
34735  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
34736  DUK_ASSERT(duk_is_number(ctx, -1));
34737  DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
34738  (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
34739  duk_remove_m2(ctx);
34740 
34741  done:
34742  return duk_get_number(ctx, -1);
34743 }
34744 
34745 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_context *ctx) {
34746  duk_hthread *thr = (duk_hthread *) ctx;
34747  duk_idx_t nargs;
34748  duk_hobject *h_this;
34749 
34750  DUK_UNREF(thr);
34751 
34752  /*
34753  * The Number constructor uses ToNumber(arg) for number coercion
34754  * (coercing an undefined argument to NaN). However, if the
34755  * argument is not given at all, +0 must be used instead. To do
34756  * this, a vararg function is used.
34757  */
34758 
34759  nargs = duk_get_top(ctx);
34760  if (nargs == 0) {
34761  duk_push_int(ctx, 0);
34762  }
34763  duk_to_number(ctx, 0);
34764  duk_set_top(ctx, 1);
34765  DUK_ASSERT_TOP(ctx, 1);
34766 
34767  if (!duk_is_constructor_call(ctx)) {
34768  return 1;
34769  }
34770 
34771  /*
34772  * E5 Section 15.7.2.1 requires that the constructed object
34773  * must have the original Number.prototype as its internal
34774  * prototype. However, since Number.prototype is non-writable
34775  * and non-configurable, this doesn't have to be enforced here:
34776  * The default object (bound to 'this') is OK, though we have
34777  * to change its class.
34778  *
34779  * Internal value set to ToNumber(arg) or +0; if no arg given,
34780  * ToNumber(undefined) = NaN, so special treatment is needed
34781  * (above). String internal value is immutable.
34782  */
34783 
34784  /* XXX: helper */
34785  duk_push_this(ctx);
34786  h_this = duk_known_hobject(ctx, -1);
34787  DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
34788 
34789  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
34790  DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
34791  DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
34792 
34793  duk_dup_0(ctx); /* -> [ val obj val ] */
34794  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
34795  return 0; /* no return value -> don't replace created value */
34796 }
34797 
34798 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx) {
34799  (void) duk__push_this_number_plain(ctx);
34800  return 1;
34801 }
34802 
34803 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx) {
34804  duk_small_int_t radix;
34805  duk_small_uint_t n2s_flags;
34806 
34807  (void) duk__push_this_number_plain(ctx);
34808  if (duk_is_undefined(ctx, 0)) {
34809  radix = 10;
34810  } else {
34811  radix = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 2, 36);
34812  }
34813  DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
34814 
34815  n2s_flags = 0;
34816 
34817  duk_numconv_stringify(ctx,
34818  radix /*radix*/,
34819  0 /*digits*/,
34820  n2s_flags /*flags*/);
34821  return 1;
34822 }
34823 
34824 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx) {
34825  /* XXX: just use toString() for now; permitted although not recommended.
34826  * nargs==1, so radix is passed to toString().
34827  */
34828  return duk_bi_number_prototype_to_string(ctx);
34829 }
34830 
34831 /*
34832  * toFixed(), toExponential(), toPrecision()
34833  */
34834 
34835 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
34836 
34837 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx) {
34838  duk_small_int_t frac_digits;
34839  duk_double_t d;
34840  duk_small_int_t c;
34841  duk_small_uint_t n2s_flags;
34842 
34843  frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
34844  d = duk__push_this_number_plain(ctx);
34845 
34846  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
34847  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
34848  goto use_to_string;
34849  }
34850 
34851  if (d >= 1.0e21 || d <= -1.0e21) {
34852  goto use_to_string;
34853  }
34854 
34855  n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
34856  DUK_N2S_FLAG_FRACTION_DIGITS;
34857 
34858  duk_numconv_stringify(ctx,
34859  10 /*radix*/,
34860  frac_digits /*digits*/,
34861  n2s_flags /*flags*/);
34862  return 1;
34863 
34864  use_to_string:
34865  DUK_ASSERT_TOP(ctx, 2);
34866  duk_to_string(ctx, -1);
34867  return 1;
34868 }
34869 
34870 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx) {
34871  duk_bool_t frac_undefined;
34872  duk_small_int_t frac_digits;
34873  duk_double_t d;
34874  duk_small_int_t c;
34875  duk_small_uint_t n2s_flags;
34876 
34877  d = duk__push_this_number_plain(ctx);
34878 
34879  frac_undefined = duk_is_undefined(ctx, 0);
34880  duk_to_int(ctx, 0); /* for side effects */
34881 
34882  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
34883  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
34884  goto use_to_string;
34885  }
34886 
34887  frac_digits = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 0, 20);
34888 
34889  n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
34890  (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
34891 
34892  duk_numconv_stringify(ctx,
34893  10 /*radix*/,
34894  frac_digits + 1 /*leading digit + fractions*/,
34895  n2s_flags /*flags*/);
34896  return 1;
34897 
34898  use_to_string:
34899  DUK_ASSERT_TOP(ctx, 2);
34900  duk_to_string(ctx, -1);
34901  return 1;
34902 }
34903 
34904 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx) {
34905  /* The specification has quite awkward order of coercion and
34906  * checks for toPrecision(). The operations below are a bit
34907  * reordered, within constraints of observable side effects.
34908  */
34909 
34910  duk_double_t d;
34911  duk_small_int_t prec;
34912  duk_small_int_t c;
34913  duk_small_uint_t n2s_flags;
34914 
34915  DUK_ASSERT_TOP(ctx, 1);
34916 
34917  d = duk__push_this_number_plain(ctx);
34918  if (duk_is_undefined(ctx, 0)) {
34919  goto use_to_string;
34920  }
34921  DUK_ASSERT_TOP(ctx, 2);
34922 
34923  duk_to_int(ctx, 0); /* for side effects */
34924 
34925  c = (duk_small_int_t) DUK_FPCLASSIFY(d);
34926  if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
34927  goto use_to_string;
34928  }
34929 
34930  prec = (duk_small_int_t) duk_to_int_check_range(ctx, 0, 1, 21);
34931 
34932  n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
34933  DUK_N2S_FLAG_NO_ZERO_PAD;
34934 
34935  duk_numconv_stringify(ctx,
34936  10 /*radix*/,
34937  prec /*digits*/,
34938  n2s_flags /*flags*/);
34939  return 1;
34940 
34941  use_to_string:
34942  /* Used when precision is undefined; also used for NaN (-> "NaN"),
34943  * and +/- infinity (-> "Infinity", "-Infinity").
34944  */
34945 
34946  DUK_ASSERT_TOP(ctx, 2);
34947  duk_to_string(ctx, -1);
34948  return 1;
34949 }
34950 
34951 #endif /* DUK_USE_NUMBER_BUILTIN */
34952 /*
34953  * Object built-ins
34954  */
34955 
34956 /* #include duk_internal.h -> already included */
34957 
34958 /* Needed even when Object built-in disabled. */
34959 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
34960  duk_tval *tv;
34961  tv = DUK_HTHREAD_THIS_PTR((duk_hthread *) ctx);
34962  /* XXX: This is not entirely correct anymore; in ES2015 the
34963  * default lookup should use @@toStringTag to come up with
34964  * e.g. [object Symbol].
34965  */
34966  duk_push_class_string_tval(ctx, tv);
34967  return 1;
34968 }
34969 
34970 #if defined(DUK_USE_OBJECT_BUILTIN)
34971 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
34972  duk_uint_t arg_mask;
34973 
34974  arg_mask = duk_get_type_mask(ctx, 0);
34975 
34976  if (!duk_is_constructor_call(ctx) && /* not a constructor call */
34977  ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) { /* and argument not null or undefined */
34978  duk_to_object(ctx, 0);
34979  return 1;
34980  }
34981 
34982  /* Pointer and buffer primitive values are treated like other
34983  * primitives values which have a fully fledged object counterpart:
34984  * promote to an object value. Lightfuncs and plain buffers are
34985  * coerced with ToObject() even they could also be returned as is.
34986  */
34987  if (arg_mask & (DUK_TYPE_MASK_OBJECT |
34988  DUK_TYPE_MASK_STRING |
34989  DUK_TYPE_MASK_BOOLEAN |
34990  DUK_TYPE_MASK_NUMBER |
34991  DUK_TYPE_MASK_POINTER |
34992  DUK_TYPE_MASK_BUFFER |
34993  DUK_TYPE_MASK_LIGHTFUNC)) {
34994  /* For DUK_TYPE_OBJECT the coercion is a no-op and could
34995  * be checked for explicitly, but Object(obj) calls are
34996  * not very common so opt for minimal footprint.
34997  */
34998  duk_to_object(ctx, 0);
34999  return 1;
35000  }
35001 
35002  (void) duk_push_object_helper(ctx,
35003  DUK_HOBJECT_FLAG_EXTENSIBLE |
35004  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
35005  DUK_BIDX_OBJECT_PROTOTYPE);
35006  return 1;
35007 }
35008 #endif /* DUK_USE_OBJECT_BUILTIN */
35009 
35010 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
35011 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx) {
35012  duk_idx_t nargs;
35013  duk_int_t idx;
35014 
35015  nargs = duk_get_top_require_min(ctx, 1 /*min_top*/);
35016 
35017  duk_to_object(ctx, 0);
35018  for (idx = 1; idx < nargs; idx++) {
35019  /* E7 19.1.2.1 (step 4a) */
35020  if (duk_is_null_or_undefined(ctx, idx)) {
35021  continue;
35022  }
35023 
35024  /* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
35025  * convenient here.
35026  */
35027  duk_to_object(ctx, idx);
35028  duk_enum(ctx, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
35029  while (duk_next(ctx, -1, 1 /*get_value*/)) {
35030  /* [ target ... enum key value ] */
35031  duk_put_prop(ctx, 0);
35032  /* [ target ... enum ] */
35033  }
35034  /* Could pop enumerator, but unnecessary because of duk_set_top()
35035  * below.
35036  */
35037  }
35038 
35039  duk_set_top(ctx, 1);
35040  return 1;
35041 }
35042 #endif
35043 
35044 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
35045 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx) {
35046  DUK_ASSERT_TOP(ctx, 2);
35047  duk_push_boolean(ctx, duk_samevalue(ctx, 0, 1));
35048  return 1;
35049 }
35050 #endif
35051 
35052 #if defined(DUK_USE_OBJECT_BUILTIN)
35053 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
35054  duk_hobject *proto;
35055 
35056  DUK_ASSERT_TOP(ctx, 2);
35057 
35058 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
35059  duk_hbufobj_promote_plain(ctx, 0);
35060 #endif
35061  proto = duk_require_hobject_accept_mask(ctx, 0, DUK_TYPE_MASK_NULL);
35062  DUK_ASSERT(proto != NULL || duk_is_null(ctx, 0));
35063 
35064  (void) duk_push_object_helper_proto(ctx,
35065  DUK_HOBJECT_FLAG_EXTENSIBLE |
35066  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
35067  proto);
35068 
35069  if (!duk_is_undefined(ctx, 1)) {
35070  /* [ O Properties obj ] */
35071 
35072  duk_replace(ctx, 0);
35073 
35074  /* [ obj Properties ] */
35075 
35076  /* Just call the "original" Object.defineProperties() to
35077  * finish up.
35078  */
35079 
35080  return duk_bi_object_constructor_define_properties(ctx);
35081  }
35082 
35083  /* [ O Properties obj ] */
35084 
35085  return 1;
35086 }
35087 #endif /* DUK_USE_OBJECT_BUILTIN */
35088 
35089 #if defined(DUK_USE_OBJECT_BUILTIN)
35090 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) {
35091  duk_small_uint_t pass;
35092  duk_uint_t defprop_flags;
35093  duk_hobject *obj;
35094  duk_idx_t idx_value;
35095  duk_hobject *get;
35096  duk_hobject *set;
35097 
35098  /* Lightfunc and plain buffer handling by ToObject() coercion. */
35099  obj = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35100  DUK_ASSERT(obj != NULL);
35101 
35102  duk_to_object(ctx, 1); /* properties object */
35103 
35104  DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
35105  (duk_tval *) duk_get_tval(ctx, 0),
35106  (duk_tval *) duk_get_tval(ctx, 1)));
35107 
35108  /*
35109  * Two pass approach to processing the property descriptors.
35110  * On first pass validate and normalize all descriptors before
35111  * any changes are made to the target object. On second pass
35112  * make the actual modifications to the target object.
35113  *
35114  * Right now we'll just use the same normalize/validate helper
35115  * on both passes, ignoring its outputs on the first pass.
35116  */
35117 
35118  for (pass = 0; pass < 2; pass++) {
35119  duk_set_top(ctx, 2); /* -> [ hobject props ] */
35120  duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
35121 
35122  for (;;) {
35123  duk_hstring *key;
35124 
35125  /* [ hobject props enum(props) ] */
35126 
35127  duk_set_top(ctx, 3);
35128 
35129  if (!duk_next(ctx, 2, 1 /*get_value*/)) {
35130  break;
35131  }
35132 
35133  DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
35134  (duk_tval *) duk_get_tval(ctx, -2),
35135  (duk_tval *) duk_get_tval(ctx, -1)));
35136 
35137  /* [ hobject props enum(props) key desc ] */
35138 
35139  duk_hobject_prepare_property_descriptor(ctx,
35140  4 /*idx_desc*/,
35141  &defprop_flags,
35142  &idx_value,
35143  &get,
35144  &set);
35145 
35146  /* [ hobject props enum(props) key desc [multiple values] ] */
35147 
35148  if (pass == 0) {
35149  continue;
35150  }
35151 
35152  /* This allows symbols on purpose. */
35153  key = duk_known_hstring(ctx, 3);
35154  DUK_ASSERT(key != NULL);
35155 
35156  duk_hobject_define_property_helper(ctx,
35157  defprop_flags,
35158  obj,
35159  key,
35160  idx_value,
35161  get,
35162  set,
35163  1 /*throw_flag*/);
35164  }
35165  }
35166 
35167  /*
35168  * Return target object
35169  */
35170 
35171  duk_dup_0(ctx);
35172  return 1;
35173 }
35174 #endif /* DUK_USE_OBJECT_BUILTIN */
35175 
35176 #if defined(DUK_USE_OBJECT_BUILTIN)
35177 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
35178  duk_hthread *thr = (duk_hthread *) ctx;
35179  duk_hobject *h;
35180  duk_bool_t is_freeze;
35181 
35182  DUK_ASSERT_TOP(ctx, 1);
35183 
35184  is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
35185  if (duk_is_buffer(ctx, 0)) {
35186  /* Plain buffer: already sealed, but not frozen (and can't be frozen
35187  * because index properties can't be made non-writable.
35188  */
35189  if (is_freeze) {
35190  goto fail_cannot_freeze;
35191  }
35192  return 1;
35193  } else if (duk_is_lightfunc(ctx, 0)) {
35194  /* Lightfunc: already sealed and frozen, success. */
35195  return 1;
35196  }
35197 #if 0
35198  /* Seal/freeze are quite rare in practice so it'd be nice to get the
35199  * correct behavior simply via automatic promotion (at the cost of some
35200  * memory churn). However, the promoted objects don't behave the same,
35201  * e.g. promoted lightfuncs are extensible.
35202  */
35203  h = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35204 #endif
35205 
35206  h = duk_get_hobject(ctx, 0);
35207  if (h == NULL) {
35208  /* ES2015 Sections 19.1.2.5, 19.1.2.17 */
35209  return 1;
35210  }
35211 
35212  if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
35213  /* Buffer objects cannot be frozen because there's no internal
35214  * support for making virtual array indices non-writable.
35215  */
35216  DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
35217  goto fail_cannot_freeze;
35218  }
35219 
35220  duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
35221 
35222  /* Sealed and frozen objects cannot gain any more properties,
35223  * so this is a good time to compact them.
35224  */
35225  duk_hobject_compact_props(thr, h);
35226  return 1;
35227 
35228  fail_cannot_freeze:
35229  DUK_DCERROR_TYPE_INVALID_ARGS(thr); /* XXX: proper error message */
35230 }
35231 #endif /* DUK_USE_OBJECT_BUILTIN */
35232 
35233 #if defined(DUK_USE_OBJECT_BUILTIN)
35234 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx) {
35235  duk_hobject *h;
35236  duk_bool_t is_frozen;
35237  duk_uint_t mask;
35238 
35239  is_frozen = duk_get_current_magic(ctx);
35240  mask = duk_get_type_mask(ctx, 0);
35241  if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
35242  DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
35243  duk_push_boolean(ctx, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
35244  1 : /* lightfunc always frozen and sealed */
35245  (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
35246  } else {
35247  /* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
35248  * is considered to be already sealed and frozen.
35249  */
35250  h = duk_get_hobject(ctx, 0);
35251  duk_push_boolean(ctx, (h == NULL) ||
35252  duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/));
35253  }
35254  return 1;
35255 }
35256 #endif /* DUK_USE_OBJECT_BUILTIN */
35257 
35258 #if defined(DUK_USE_OBJECT_BUILTIN)
35259 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx) {
35260  DUK_ASSERT_TOP(ctx, 0);
35261  (void) duk_push_this_coercible_to_object(ctx);
35262  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_TO_STRING);
35263 #if 0 /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
35264  duk_require_callable(ctx, 1);
35265 #endif
35266  duk_dup_0(ctx); /* -> [ O toString O ] */
35267  duk_call_method(ctx, 0); /* XXX: call method tail call? */
35268  return 1;
35269 }
35270 #endif /* DUK_USE_OBJECT_BUILTIN */
35271 
35272 #if defined(DUK_USE_OBJECT_BUILTIN)
35273 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
35274  /* For lightfuncs and plain buffers, returns Object() coerced. */
35275  (void) duk_push_this_coercible_to_object(ctx);
35276  return 1;
35277 }
35278 #endif /* DUK_USE_OBJECT_BUILTIN */
35279 
35280 #if defined(DUK_USE_OBJECT_BUILTIN)
35281 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx) {
35282  duk_hthread *thr = (duk_hthread *) ctx;
35283  duk_hobject *h_v;
35284  duk_hobject *h_obj;
35285 
35286  DUK_ASSERT_TOP(ctx, 1);
35287 
35288  h_v = duk_get_hobject(ctx, 0);
35289  if (!h_v) {
35290  duk_push_false(ctx); /* XXX: tail call: return duk_push_false(ctx) */
35291  return 1;
35292  }
35293 
35294  h_obj = duk_push_this_coercible_to_object(ctx);
35295  DUK_ASSERT(h_obj != NULL);
35296 
35297  /* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
35298  * Prototype loops should cause an error to be thrown.
35299  */
35300  duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
35301  return 1;
35302 }
35303 #endif /* DUK_USE_OBJECT_BUILTIN */
35304 
35305 #if defined(DUK_USE_OBJECT_BUILTIN)
35306 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx) {
35307  return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
35308 }
35309 #endif /* DUK_USE_OBJECT_BUILTIN */
35310 
35311 #if defined(DUK_USE_OBJECT_BUILTIN)
35312 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
35313  return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
35314 }
35315 #endif /* DUK_USE_OBJECT_BUILTIN */
35316 
35317 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35318 /* Shared helper to implement Object.getPrototypeOf,
35319  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
35320  *
35321  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
35322  */
35323 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
35324  /*
35325  * magic = 0: __proto__ getter
35326  * magic = 1: Object.getPrototypeOf()
35327  * magic = 2: Reflect.getPrototypeOf()
35328  */
35329 
35330  duk_hthread *thr = (duk_hthread *) ctx;
35331  duk_hobject *h;
35332  duk_hobject *proto;
35333  duk_tval *tv;
35334  duk_int_t magic;
35335 
35336  magic = duk_get_current_magic(ctx);
35337 
35338  if (magic == 0) {
35339  DUK_ASSERT_TOP(ctx, 0);
35340  duk_push_this_coercible_to_object(ctx);
35341  }
35342  DUK_ASSERT(duk_get_top(ctx) >= 1);
35343  if (magic < 2) {
35344  /* ES2015 Section 19.1.2.9, step 1 */
35345  duk_to_object(ctx, 0);
35346  }
35347  tv = DUK_GET_TVAL_POSIDX(ctx, 0);
35348 
35349  switch (DUK_TVAL_GET_TAG(tv)) {
35350  case DUK_TAG_BUFFER:
35351  proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
35352  break;
35353  case DUK_TAG_LIGHTFUNC:
35354  proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
35355  break;
35356  case DUK_TAG_OBJECT:
35357  h = DUK_TVAL_GET_OBJECT(tv);
35358  proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
35359  break;
35360  default:
35361  /* This implicitly handles CheckObjectCoercible() caused
35362  * TypeError.
35363  */
35364  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35365  }
35366  if (proto != NULL) {
35367  duk_push_hobject(ctx, proto);
35368  } else {
35369  duk_push_null(ctx);
35370  }
35371  return 1;
35372 }
35373 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35374 
35375 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35376 /* Shared helper to implement ES2015 Object.setPrototypeOf,
35377  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
35378  *
35379  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
35380  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
35381  */
35382 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
35383  /*
35384  * magic = 0: __proto__ setter
35385  * magic = 1: Object.setPrototypeOf()
35386  * magic = 2: Reflect.setPrototypeOf()
35387  */
35388 
35389  duk_hthread *thr = (duk_hthread *) ctx;
35390  duk_hobject *h_obj;
35391  duk_hobject *h_new_proto;
35392  duk_hobject *h_curr;
35393  duk_ret_t ret_success = 1; /* retval for success path */
35394  duk_uint_t mask;
35395  duk_int_t magic;
35396 
35397  /* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
35398  magic = duk_get_current_magic(ctx);
35399  if (magic == 0) {
35400  duk_push_this_check_object_coercible(ctx);
35401  duk_insert(ctx, 0);
35402  if (!duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
35403  return 0;
35404  }
35405 
35406  /* __proto__ setter returns 'undefined' on success unlike the
35407  * setPrototypeOf() call which returns the target object.
35408  */
35409  ret_success = 0;
35410  } else {
35411  if (magic == 1) {
35412  duk_require_object_coercible(ctx, 0);
35413  } else {
35414  duk_require_hobject_accept_mask(ctx, 0,
35415  DUK_TYPE_MASK_LIGHTFUNC |
35416  DUK_TYPE_MASK_BUFFER);
35417  }
35418  duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
35419  }
35420 
35421  h_new_proto = duk_get_hobject(ctx, 1);
35422  /* h_new_proto may be NULL */
35423 
35424  mask = duk_get_type_mask(ctx, 0);
35425  if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
35426  duk_hobject *curr_proto;
35427  curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
35428  DUK_BIDX_FUNCTION_PROTOTYPE :
35429  DUK_BIDX_UINT8ARRAY_PROTOTYPE];
35430  if (h_new_proto == curr_proto) {
35431  goto skip;
35432  }
35433  goto fail_nonextensible;
35434  }
35435  h_obj = duk_get_hobject(ctx, 0);
35436  if (h_obj == NULL) {
35437  goto skip;
35438  }
35439  DUK_ASSERT(h_obj != NULL);
35440 
35441  /* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
35442  /* TODO: implement Proxy object support here */
35443 
35444  if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
35445  goto skip;
35446  }
35447  if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
35448  goto fail_nonextensible;
35449  }
35450  for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
35451  /* Loop prevention. */
35452  if (h_curr == h_obj) {
35453  goto fail_loop;
35454  }
35455  }
35456  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
35457  /* fall thru */
35458 
35459  skip:
35460  duk_set_top(ctx, 1);
35461  if (magic == 2) {
35462  duk_push_true(ctx);
35463  }
35464  return ret_success;
35465 
35466  fail_nonextensible:
35467  fail_loop:
35468  if (magic != 2) {
35469  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
35470  } else {
35471  duk_push_false(ctx);
35472  return 1;
35473  }
35474 }
35475 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35476 
35477 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35478 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx) {
35479  /*
35480  * magic = 0: Object.defineProperty()
35481  * magic = 1: Reflect.defineProperty()
35482  */
35483 
35484  duk_hobject *obj;
35485  duk_hstring *key;
35486  duk_hobject *get;
35487  duk_hobject *set;
35488  duk_idx_t idx_value;
35489  duk_uint_t defprop_flags;
35490  duk_int_t magic;
35491  duk_bool_t throw_flag;
35492  duk_bool_t ret;
35493 
35494  DUK_ASSERT(ctx != NULL);
35495 
35496  DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
35497  (void *) ctx,
35498  (duk_tval *) duk_get_tval(ctx, 0),
35499  (duk_tval *) duk_get_tval(ctx, 1),
35500  (duk_tval *) duk_get_tval(ctx, 2)));
35501 
35502  /* [ obj key desc ] */
35503 
35504  magic = duk_get_current_magic(ctx);
35505 
35506  /* Lightfuncs are currently supported by coercing to a temporary
35507  * Function object; changes will be allowed (the coerced value is
35508  * extensible) but will be lost. Same for plain buffers.
35509  */
35510  obj = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35511  DUK_ASSERT(obj != NULL);
35512  key = duk_to_property_key_hstring(ctx, 1);
35513  (void) duk_require_hobject(ctx, 2);
35514 
35515  DUK_ASSERT(obj != NULL);
35516  DUK_ASSERT(key != NULL);
35517  DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
35518 
35519  /*
35520  * Validate and convert argument property descriptor (an Ecmascript
35521  * object) into a set of defprop_flags and possibly property value,
35522  * getter, and/or setter values on the value stack.
35523  *
35524  * Lightfunc set/get values are coerced to full Functions.
35525  */
35526 
35527  duk_hobject_prepare_property_descriptor(ctx,
35528  2 /*idx_desc*/,
35529  &defprop_flags,
35530  &idx_value,
35531  &get,
35532  &set);
35533 
35534  /*
35535  * Use Object.defineProperty() helper for the actual operation.
35536  */
35537 
35538  DUK_ASSERT(magic == 0 || magic == 1);
35539  throw_flag = magic ^ 1;
35540  ret = duk_hobject_define_property_helper(ctx,
35541  defprop_flags,
35542  obj,
35543  key,
35544  idx_value,
35545  get,
35546  set,
35547  throw_flag);
35548 
35549  /* Ignore the normalize/validate helper outputs on the value stack,
35550  * they're popped automatically.
35551  */
35552 
35553  if (magic == 0) {
35554  /* Object.defineProperty(): return target object. */
35555  duk_push_hobject(ctx, obj);
35556  } else {
35557  /* Reflect.defineProperty(): return success/fail. */
35558  duk_push_boolean(ctx, ret);
35559  }
35560  return 1;
35561 }
35562 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35563 
35564 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35565 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx) {
35566  DUK_ASSERT_TOP(ctx, 2);
35567 
35568  /* ES2015 Section 19.1.2.6, step 1 */
35569  if (duk_get_current_magic(ctx) == 0) {
35570  duk_to_object(ctx, 0);
35571  }
35572 
35573  /* [ obj key ] */
35574 
35575  duk_hobject_object_get_own_property_descriptor(ctx, -2);
35576  return 1;
35577 }
35578 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35579 
35580 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35581 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx) {
35582  /*
35583  * magic = 0: Object.isExtensible()
35584  * magic = 1: Reflect.isExtensible()
35585  */
35586 
35587  duk_hobject *h;
35588 
35589  if (duk_get_current_magic(ctx) == 0) {
35590  h = duk_get_hobject(ctx, 0);
35591  } else {
35592  /* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
35593  * and plain buffers here because they pretend to be objects.
35594  */
35595  h = duk_require_hobject_accept_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35596  }
35597 
35598  duk_push_boolean(ctx, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
35599  return 1;
35600 }
35601 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35602 
35603 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35604 /* Shared helper for various key/symbol listings, magic:
35605  * 0=Object.keys()
35606  * 1=Object.getOwnPropertyNames(),
35607  * 2=Object.getOwnPropertySymbols(),
35608  * 3=Reflect.ownKeys()
35609  */
35610 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
35611  /* Object.keys() */
35612  DUK_ENUM_OWN_PROPERTIES_ONLY |
35613  DUK_ENUM_NO_PROXY_BEHAVIOR,
35614 
35615  /* Object.getOwnPropertyNames() */
35616  DUK_ENUM_INCLUDE_NONENUMERABLE |
35617  DUK_ENUM_OWN_PROPERTIES_ONLY |
35618  DUK_ENUM_NO_PROXY_BEHAVIOR,
35619 
35620  /* Object.getOwnPropertySymbols() */
35621  DUK_ENUM_INCLUDE_SYMBOLS |
35622  DUK_ENUM_OWN_PROPERTIES_ONLY |
35623  DUK_ENUM_EXCLUDE_STRINGS |
35624  DUK_ENUM_INCLUDE_NONENUMERABLE |
35625  DUK_ENUM_NO_PROXY_BEHAVIOR,
35626 
35627  /* Reflect.ownKeys() */
35628  DUK_ENUM_INCLUDE_SYMBOLS |
35629  DUK_ENUM_OWN_PROPERTIES_ONLY |
35630  DUK_ENUM_INCLUDE_NONENUMERABLE |
35631  DUK_ENUM_NO_PROXY_BEHAVIOR
35632 };
35633 
35634 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
35635  duk_hthread *thr = (duk_hthread *) ctx;
35636  duk_hobject *obj;
35637 #if defined(DUK_USE_ES6_PROXY)
35638  duk_hobject *h_proxy_target;
35639  duk_hobject *h_proxy_handler;
35640  duk_hobject *h_trap_result;
35641 #endif
35642  duk_small_uint_t enum_flags;
35643  duk_int_t magic;
35644 
35645  DUK_ASSERT_TOP(ctx, 1);
35646  DUK_UNREF(thr);
35647 
35648  magic = duk_get_current_magic(ctx);
35649  if (magic == 3) {
35650  /* ES2015 Section 26.1.11 requires a TypeError for non-objects. Lightfuncs
35651  * and plain buffers pretend to be objects, so accept those too.
35652  */
35653  obj = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35654  } else {
35655  /* ES2015: ToObject coerce. */
35656  obj = duk_to_hobject(ctx, 0);
35657  }
35658  DUK_ASSERT(obj != NULL);
35659  DUK_UNREF(obj);
35660 
35661  /* XXX: proxy chains */
35662 
35663 #if defined(DUK_USE_ES6_PROXY)
35664  /* XXX: better sharing of code between proxy target call sites */
35665  if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
35666  obj,
35667  &h_proxy_target,
35668  &h_proxy_handler))) {
35669  goto skip_proxy;
35670  }
35671 
35672  duk_push_hobject(ctx, h_proxy_handler);
35673  if (!duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
35674  /* Careful with reachability here: don't pop 'obj' before pushing
35675  * proxy target.
35676  */
35677  DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
35678  duk_pop_2(ctx);
35679  duk_push_hobject(ctx, h_proxy_target);
35680  duk_replace(ctx, 0);
35681  DUK_ASSERT_TOP(ctx, 1);
35682  goto skip_proxy;
35683  }
35684 
35685  /* [ obj handler trap ] */
35686  duk_insert(ctx, -2);
35687  duk_push_hobject(ctx, h_proxy_target); /* -> [ obj trap handler target ] */
35688  duk_call_method(ctx, 1 /*nargs*/); /* -> [ obj trap_result ] */
35689  h_trap_result = duk_require_hobject(ctx, -1);
35690  DUK_UNREF(h_trap_result);
35691 
35692  magic = duk_get_current_magic(ctx);
35693  DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
35694  enum_flags = duk__object_keys_enum_flags[magic];
35695 
35696  duk_proxy_ownkeys_postprocess(ctx, h_proxy_target, enum_flags);
35697  return 1;
35698 
35699  skip_proxy:
35700 #endif /* DUK_USE_ES6_PROXY */
35701 
35702  DUK_ASSERT_TOP(ctx, 1);
35703  magic = duk_get_current_magic(ctx);
35704  DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
35705  enum_flags = duk__object_keys_enum_flags[magic];
35706  return duk_hobject_get_enumerated_keys(ctx, enum_flags);
35707 }
35708 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35709 
35710 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
35711 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
35712  /*
35713  * magic = 0: Object.preventExtensions()
35714  * magic = 1: Reflect.preventExtensions()
35715  */
35716 
35717  duk_hthread *thr = (duk_hthread *) ctx;
35718  duk_hobject *h;
35719  duk_uint_t mask;
35720  duk_int_t magic;
35721 
35722  magic = duk_get_current_magic(ctx);
35723 
35724  /* Silent success for lightfuncs and plain buffers always. */
35725  mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
35726 
35727  /* Object.preventExtensions() silent success for non-object. */
35728  if (magic == 0) {
35729  mask |= DUK_TYPE_MASK_UNDEFINED |
35730  DUK_TYPE_MASK_NULL |
35731  DUK_TYPE_MASK_BOOLEAN |
35732  DUK_TYPE_MASK_NUMBER |
35733  DUK_TYPE_MASK_STRING |
35734  DUK_TYPE_MASK_POINTER;
35735  }
35736 
35737  if (duk_check_type_mask(ctx, 0, mask)) {
35738  /* Not an object, already non-extensible so always success. */
35739  goto done;
35740  }
35741  h = duk_require_hobject(ctx, 0);
35742  DUK_ASSERT(h != NULL);
35743 
35744  DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
35745 
35746  /* A non-extensible object cannot gain any more properties,
35747  * so this is a good time to compact.
35748  */
35749  duk_hobject_compact_props(thr, h);
35750 
35751  done:
35752  if (magic == 1) {
35753  duk_push_true(ctx);
35754  }
35755  return 1;
35756 }
35757 #endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
35758 /*
35759  * Pointer built-ins
35760  */
35761 
35762 /* #include duk_internal.h -> already included */
35763 
35764 /*
35765  * Constructor
35766  */
35767 
35768 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx) {
35769  /* XXX: this behavior is quite useless now; it would be nice to be able
35770  * to create pointer values from e.g. numbers or strings. Numbers are
35771  * problematic on 64-bit platforms though. Hex encoded strings?
35772  */
35773  if (duk_get_top(ctx) == 0) {
35774  duk_push_pointer(ctx, NULL);
35775  } else {
35776  duk_to_pointer(ctx, 0);
35777  }
35778  DUK_ASSERT(duk_is_pointer(ctx, 0));
35779  duk_set_top(ctx, 1);
35780 
35781  if (duk_is_constructor_call(ctx)) {
35782  (void) duk_push_object_helper(ctx,
35783  DUK_HOBJECT_FLAG_EXTENSIBLE |
35784  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
35785  DUK_BIDX_POINTER_PROTOTYPE);
35786 
35787  /* Pointer object internal value is immutable */
35788  duk_dup_0(ctx);
35789  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
35790  }
35791  /* Note: unbalanced stack on purpose */
35792 
35793  return 1;
35794 }
35795 
35796 /*
35797  * toString(), valueOf()
35798  */
35799 
35800 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx) {
35801  duk_tval *tv;
35802  duk_small_int_t to_string = duk_get_current_magic(ctx);
35803 
35804  duk_push_this(ctx);
35805  tv = duk_require_tval(ctx, -1);
35806  DUK_ASSERT(tv != NULL);
35807 
35808  if (DUK_TVAL_IS_POINTER(tv)) {
35809  /* nop */
35810  } else if (DUK_TVAL_IS_OBJECT(tv)) {
35811  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
35812  DUK_ASSERT(h != NULL);
35813 
35814  /* Must be a "pointer object", i.e. class "Pointer" */
35815  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
35816  goto type_error;
35817  }
35818 
35819  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
35820  } else {
35821  goto type_error;
35822  }
35823 
35824  if (to_string) {
35825  duk_to_string(ctx, -1);
35826  }
35827  return 1;
35828 
35829  type_error:
35830  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
35831 }
35832 /*
35833  * Proxy built-in (ES2015)
35834  */
35835 
35836 /* #include duk_internal.h -> already included */
35837 
35838 #if defined(DUK_USE_ES6_PROXY)
35839 /* Post-process a Proxy ownKeys() result at stack top. Push a cleaned up
35840  * array of valid result keys (strings or symbols). TypeError for invalid
35841  * values. Flags are shared with duk_enum().
35842  */
35843 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_context *ctx, duk_hobject *h_proxy_target, duk_uint_t flags) {
35844  duk_hthread *thr = (duk_hthread *) ctx;
35845  duk_uarridx_t i, len, idx;
35846  duk_propdesc desc;
35847 
35848  DUK_ASSERT_CTX_VALID(ctx);
35849  DUK_ASSERT(h_proxy_target != NULL);
35850 
35851  len = (duk_uarridx_t) duk_get_length(ctx, -1);
35852  idx = 0;
35853  duk_push_array(ctx);
35854  /* XXX: preallocated dense array, fill in directly */
35855  for (i = 0; i < len; i++) {
35856  duk_hstring *h;
35857 
35858  /* [ obj trap_result res_arr ] */
35859  (void) duk_get_prop_index(ctx, -2, i);
35860  h = duk_get_hstring(ctx, -1);
35861  if (h == NULL) {
35862  DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
35863  }
35864 
35865  if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
35866  /* No support for 'getOwnPropertyDescriptor' trap yet,
35867  * so check enumerability always from target object
35868  * descriptor.
35869  */
35870  if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(ctx, -1), &desc, 0 /*flags*/)) {
35871  if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
35872  DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(ctx, -1)));
35873  goto skip_key;
35874  }
35875  } else {
35876  DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(ctx, -1)));
35877  goto skip_key;
35878  }
35879  }
35880  if (DUK_HSTRING_HAS_SYMBOL(h)) {
35881  if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
35882  DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(ctx, -1)));
35883  goto skip_key;
35884  }
35885  if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
35886  DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(ctx, -1)));
35887  goto skip_key;
35888  }
35889  } else {
35890  if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
35891  DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(ctx, -1)));
35892  goto skip_key;
35893  }
35894  }
35895 
35896  /* [ obj trap_result res_arr propname ] */
35897  duk_put_prop_index(ctx, -2, idx++);
35898  continue;
35899 
35900  skip_key:
35901  duk_pop(ctx);
35902  continue;
35903  }
35904 
35905  /* XXX: Missing trap result validation for non-configurable target keys
35906  * (must be present), for non-extensible target all target keys must be
35907  * present and no extra keys can be present.
35908  * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
35909  */
35910 
35911  /* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
35912  * trap which has not yet been implemented. In the absence of such a trap,
35913  * the enumerability should be checked from the target object; this is
35914  * handled above.
35915  */
35916 }
35917 #endif /* DUK_USE_ES6_PROXY */
35918 
35919 #if defined(DUK_USE_ES6_PROXY)
35920 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx) {
35921  duk_hobject *h_target;
35922  duk_hobject *h_handler;
35923 
35924  duk_require_constructor_call(ctx);
35925 
35926  /* Reject a proxy object as the target because it would need
35927  * special handler in property lookups. (ES2015 has no such restriction)
35928  */
35929  h_target = duk_require_hobject_promote_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35930  DUK_ASSERT(h_target != NULL);
35931  if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_target)) {
35932  goto fail_args;
35933  }
35934 
35935  /* Reject a proxy object as the handler because it would cause
35936  * potentially unbounded recursion. (ES2015 has no such restriction)
35937  *
35938  * There's little practical reason to use a lightfunc or a plain
35939  * buffer as the handler table: one could only provide traps via
35940  * their prototype objects (Function.prototype and ArrayBuffer.prototype).
35941  * Even so, as lightfuncs and plain buffers mimic their object
35942  * counterparts, they're promoted and accepted here.
35943  */
35944  h_handler = duk_require_hobject_promote_mask(ctx, 1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
35945  DUK_ASSERT(h_handler != NULL);
35946  if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h_handler)) {
35947  goto fail_args;
35948  }
35949 
35950  /* XXX: the returned value is exotic in ES2015, but we use a
35951  * simple object here with no prototype. Without a prototype,
35952  * ToPrimitive() coercion fails which is a bit confusing.
35953  * No callable check/handling in the current Proxy subset.
35954  */
35955  (void) duk_push_object_helper_proto(ctx,
35956  DUK_HOBJECT_FLAG_EXTENSIBLE |
35957  DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ |
35958  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
35959  NULL);
35960  DUK_ASSERT_TOP(ctx, 3);
35961 
35962  /* Make _Target and _Handler non-configurable and non-writable.
35963  * They can still be forcibly changed by C code (both user and
35964  * Duktape internal), but not by Ecmascript code.
35965  */
35966 
35967  /* Proxy target */
35968  duk_dup_0(ctx);
35969  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
35970 
35971  /* Proxy handler */
35972  duk_dup_1(ctx);
35973  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_HANDLER, DUK_PROPDESC_FLAGS_NONE);
35974 
35975  return 1; /* replacement handler */
35976 
35977  fail_args:
35978  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
35979 }
35980 #endif /* DUK_USE_ES6_PROXY */
35981 /*
35982  * 'Reflect' built-in (ES2016 Section 26.1)
35983  * http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
35984  *
35985  * Many Reflect built-in functions are provided by shared helpers in
35986  * duk_bi_object.c or duk_bi_function.c.
35987  */
35988 
35989 /* #include duk_internal.h -> already included */
35990 
35991 #if defined(DUK_USE_REFLECT_BUILTIN)
35992 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx) {
35993  duk_hthread *thr;
35994  duk_tval *tv_obj;
35995  duk_tval *tv_key;
35996  duk_bool_t ret;
35997 
35998  DUK_ASSERT_TOP(ctx, 2);
35999  (void) duk_require_hobject(ctx, 0);
36000  (void) duk_to_string(ctx, 1);
36001 
36002  /* [ target key ] */
36003 
36004  thr = (duk_hthread *) ctx;
36005  DUK_ASSERT(thr != NULL);
36006  tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
36007  tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
36008  ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
36009  duk_push_boolean(ctx, ret);
36010  return 1;
36011 }
36012 
36013 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx) {
36014  duk_hthread *thr;
36015  duk_tval *tv_obj;
36016  duk_tval *tv_key;
36017  duk_idx_t nargs;
36018 
36019  nargs = duk_get_top_require_min(ctx, 2 /*min_top*/);
36020  (void) duk_require_hobject(ctx, 0);
36021  (void) duk_to_string(ctx, 1);
36022  if (nargs >= 3 && !duk_strict_equals(ctx, 0, 2)) {
36023  /* XXX: [[Get]] receiver currently unsupported */
36024  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
36025  }
36026 
36027  /* [ target key receiver? ...? ] */
36028 
36029  thr = (duk_hthread *) ctx;
36030  DUK_ASSERT(thr != NULL);
36031  tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
36032  tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
36033  (void) duk_hobject_getprop(thr, tv_obj, tv_key); /* This could also be a duk_get_prop(). */
36034  return 1;
36035 }
36036 
36037 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx) {
36038  duk_hthread *thr;
36039  duk_tval *tv_obj;
36040  duk_tval *tv_key;
36041  duk_bool_t ret;
36042 
36043  DUK_ASSERT_TOP(ctx, 2);
36044  (void) duk_require_hobject(ctx, 0);
36045  (void) duk_to_string(ctx, 1);
36046 
36047  /* [ target key ] */
36048 
36049  thr = (duk_hthread *) ctx;
36050  DUK_ASSERT(thr != NULL);
36051  tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
36052  tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
36053  ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
36054  duk_push_boolean(ctx, ret);
36055  return 1;
36056 }
36057 
36058 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx) {
36059  duk_hthread *thr;
36060  duk_tval *tv_obj;
36061  duk_tval *tv_key;
36062  duk_tval *tv_val;
36063  duk_idx_t nargs;
36064  duk_bool_t ret;
36065 
36066  nargs = duk_get_top_require_min(ctx, 3 /*min_top*/);
36067  (void) duk_require_hobject(ctx, 0);
36068  (void) duk_to_string(ctx, 1);
36069  if (nargs >= 4 && !duk_strict_equals(ctx, 0, 3)) {
36070  /* XXX: [[Set]] receiver currently unsupported */
36071  DUK_ERROR_UNSUPPORTED((duk_hthread *) ctx);
36072  }
36073 
36074  /* [ target key value receiver? ...? ] */
36075 
36076  thr = (duk_hthread *) ctx;
36077  DUK_ASSERT(thr != NULL);
36078  tv_obj = DUK_GET_TVAL_POSIDX(ctx, 0);
36079  tv_key = DUK_GET_TVAL_POSIDX(ctx, 1);
36080  tv_val = DUK_GET_TVAL_POSIDX(ctx, 2);
36081  ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
36082  duk_push_boolean(ctx, ret);
36083  return 1;
36084 }
36085 #endif /* DUK_USE_REFLECT_BUILTIN */
36086 /*
36087  * RegExp built-ins
36088  */
36089 
36090 /* #include duk_internal.h -> already included */
36091 
36092 #if defined(DUK_USE_REGEXP_SUPPORT)
36093 
36094 DUK_LOCAL void duk__get_this_regexp(duk_context *ctx) {
36095  duk_hobject *h;
36096 
36097  duk_push_this(ctx);
36098  h = duk_require_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_REGEXP);
36099  DUK_ASSERT(h != NULL);
36100  DUK_UNREF(h);
36101  duk_insert(ctx, 0); /* prepend regexp to valstack 0 index */
36102 }
36103 
36104 /* XXX: much to improve (code size) */
36105 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx) {
36106  duk_hthread *thr = (duk_hthread *) ctx;
36107  duk_hobject *h_pattern;
36108 
36109  DUK_ASSERT_TOP(ctx, 2);
36110  h_pattern = duk_get_hobject(ctx, 0);
36111 
36112  if (!duk_is_constructor_call(ctx) &&
36113  h_pattern != NULL &&
36114  DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
36115  duk_is_undefined(ctx, 1)) {
36116  /* Called as a function, pattern has [[Class]] "RegExp" and
36117  * flags is undefined -> return object as is.
36118  */
36119  /* XXX: ES2015 has a NewTarget SameValue() check which is not
36120  * yet implemented.
36121  */
36122  duk_dup_0(ctx);
36123  return 1;
36124  }
36125 
36126  /* Else functionality is identical for function call and constructor
36127  * call.
36128  */
36129 
36130  if (h_pattern != NULL &&
36131  DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
36132  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_SOURCE);
36133  if (duk_is_undefined(ctx, 1)) {
36134  /* In ES5 one would need to read the flags individually;
36135  * in ES2015 just read .flags.
36136  */
36137  duk_get_prop_stridx(ctx, 0, DUK_STRIDX_FLAGS);
36138  } else {
36139  /* In ES2015 allowed; overrides argument RegExp flags. */
36140  duk_dup_1(ctx);
36141  }
36142  } else {
36143  if (duk_is_undefined(ctx, 0)) {
36144  duk_push_hstring_empty(ctx);
36145  } else {
36146  duk_dup_0(ctx);
36147  duk_to_string(ctx, -1); /* Rejects Symbols. */
36148  }
36149  if (duk_is_undefined(ctx, 1)) {
36150  duk_push_hstring_empty(ctx);
36151  } else {
36152  duk_dup_1(ctx);
36153  duk_to_string(ctx, -1); /* Rejects Symbols. */
36154  }
36155 
36156  /* [ ... pattern flags ] */
36157  }
36158 
36159  DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
36160  (duk_tval *) duk_get_tval(ctx, -2), (duk_tval *) duk_get_tval(ctx, -1)));
36161 
36162  /* [ ... pattern flags ] (both uncoerced) */
36163 
36164  duk_to_string(ctx, -2);
36165  duk_to_string(ctx, -1);
36166  duk_regexp_compile(thr);
36167 
36168  /* [ ... bytecode escaped_source ] */
36169 
36170  duk_regexp_create_instance(thr);
36171 
36172  /* [ ... RegExp ] */
36173 
36174  return 1;
36175 }
36176 
36177 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx) {
36178  duk__get_this_regexp(ctx);
36179 
36180  /* [ regexp input ] */
36181 
36182  duk_regexp_match((duk_hthread *) ctx);
36183 
36184  /* [ result ] */
36185 
36186  return 1;
36187 }
36188 
36189 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx) {
36190  duk__get_this_regexp(ctx);
36191 
36192  /* [ regexp input ] */
36193 
36194  /* result object is created and discarded; wasteful but saves code space */
36195  duk_regexp_match((duk_hthread *) ctx);
36196 
36197  /* [ result ] */
36198 
36199  duk_push_boolean(ctx, (duk_is_null(ctx, -1) ? 0 : 1));
36200 
36201  return 1;
36202 }
36203 
36204 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx) {
36205  /* This must be generic in ES2015 and later. */
36206  DUK_ASSERT_TOP(ctx, 0);
36207  duk_push_this(ctx);
36208  duk_push_string(ctx, "/");
36209  duk_get_prop_stridx(ctx, 0, DUK_STRIDX_SOURCE);
36210  duk_dup_m2(ctx); /* another "/" */
36211  duk_get_prop_stridx(ctx, 0, DUK_STRIDX_FLAGS);
36212  duk_concat(ctx, 4);
36213  return 1;
36214 }
36215 
36216 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx) {
36217  /* .flags is ES2015 but present even when ES2015 bindings are
36218  * disabled because the constructor relies on it.
36219  */
36220  duk_uint8_t buf[8]; /* enough for all flags + NUL */
36221  duk_uint8_t *p = buf;
36222 
36223  /* .flags is generic and works on any object. */
36224  duk_push_this(ctx);
36225  (void) duk_require_hobject(ctx, -1);
36226  if (duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL)) {
36227  *p++ = DUK_ASC_LC_G;
36228  }
36229  if (duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
36230  *p++ = DUK_ASC_LC_I;
36231  }
36232  if (duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_MULTILINE, NULL)) {
36233  *p++ = DUK_ASC_LC_M;
36234  }
36235  /* .unicode: to be added */
36236  /* .sticky: to be added */
36237  *p++ = DUK_ASC_NUL;
36238  DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
36239 
36240  duk_push_string(ctx, (const char *) buf);
36241  return 1;
36242 }
36243 
36244 /* Shared helper for providing .source, .global, .multiline, etc getters. */
36245 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx) {
36246  duk_hthread *thr = (duk_hthread *) ctx;
36247  duk_hstring *h_bc;
36248  duk_small_int_t re_flags;
36249  duk_hobject *h;
36250  duk_int_t magic;
36251 
36252  DUK_ASSERT_TOP(ctx, 0);
36253 
36254  duk_push_this(ctx);
36255  h = duk_require_hobject(ctx, -1);
36256  magic = duk_get_current_magic(ctx);
36257 
36258  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
36259  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_INT_SOURCE);
36260  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_INT_BYTECODE);
36261  h_bc = duk_require_hstring(ctx, -1);
36262  re_flags = (duk_small_int_t) DUK_HSTRING_GET_DATA(h_bc)[0]; /* Safe even if h_bc length is 0 (= NUL) */
36263  duk_pop(ctx);
36264  } else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
36265  /* In ES2015 and ES2016 a TypeError would be thrown here.
36266  * However, this had real world issues so ES2017 draft
36267  * allows RegExp.prototype specifically, returning '(?:)'
36268  * for .source and undefined for all flags.
36269  */
36270  if (magic != 16 /* .source */) {
36271  return 0;
36272  }
36273  duk_push_string(ctx, "(?:)"); /* .source handled by switch-case */
36274  re_flags = 0;
36275  } else {
36276  DUK_DCERROR_TYPE_INVALID_ARGS(thr);
36277  }
36278 
36279  /* [ regexp source ] */
36280 
36281  switch (magic) {
36282  case 0: { /* global */
36283  duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_GLOBAL));
36284  break;
36285  }
36286  case 1: { /* ignoreCase */
36287  duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
36288  break;
36289  }
36290  case 2: { /* multiline */
36291  duk_push_boolean(ctx, (re_flags & DUK_RE_FLAG_MULTILINE));
36292  break;
36293  }
36294 #if 0
36295  /* Don't provide until implemented to avoid interfering with feature
36296  * detection in user code.
36297  */
36298  case 3: /* sticky */
36299  case 4: { /* unicode */
36300  duk_push_false(ctx);
36301  break;
36302  }
36303 #endif
36304  default: { /* source */
36305  /* leave 'source' on top */
36306  break;
36307  }
36308  }
36309 
36310  return 1;
36311 }
36312 
36313 #endif /* DUK_USE_REGEXP_SUPPORT */
36314 /*
36315  * String built-ins
36316  *
36317  * Most String built-ins must only accept strings (or String objects).
36318  * Symbols, represented internally as strings, must be generally rejected.
36319  * The duk_push_this_coercible_to_string() helper does this automatically.
36320  */
36321 
36322 /* XXX: There are several limitations in the current implementation for
36323  * strings with >= 0x80000000UL characters. In some cases one would need
36324  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
36325  * Generally character and byte length are assumed to fit into signed 32
36326  * bits (< 0x80000000UL). Places with issues are not marked explicitly
36327  * below in all cases, look for signed type usage (duk_int_t etc) for
36328  * offsets/lengths.
36329  */
36330 
36331 /* #include duk_internal.h -> already included */
36332 
36333 #if defined(DUK_USE_STRING_BUILTIN)
36334 
36335 /*
36336  * Constructor
36337  */
36338 
36339 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_context *ctx) {
36340  duk_hstring *h;
36341  duk_uint_t flags;
36342 
36343  /* String constructor needs to distinguish between an argument not given at all
36344  * vs. given as 'undefined'. We're a vararg function to handle this properly.
36345  */
36346 
36347  /* XXX: copy current activation flags to thr, including current magic,
36348  * is_constructor_call etc. This takes a few bytes in duk_hthread but
36349  * makes call sites smaller (there are >30 is_constructor_call and get
36350  * current magic call sites.
36351  */
36352 
36353  if (duk_get_top(ctx) == 0) {
36354  duk_push_hstring_empty(ctx);
36355  } else {
36356  h = duk_to_hstring_acceptsymbol(ctx, 0);
36357  if (DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(ctx)) {
36358  duk_push_symbol_descriptive_string(ctx, h);
36359  duk_replace(ctx, 0);
36360  }
36361  }
36362  duk_to_string(ctx, 0); /* catches symbol argument for constructor call */
36363  DUK_ASSERT(duk_is_string(ctx, 0));
36364  duk_set_top(ctx, 1); /* Top may be 1 or larger. */
36365 
36366  if (duk_is_constructor_call(ctx)) {
36367  /* String object internal value is immutable */
36368  flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
36369  DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
36370  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
36371  duk_push_object_helper(ctx, flags, DUK_BIDX_STRING_PROTOTYPE);
36372  duk_dup_0(ctx);
36373  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
36374  }
36375  /* Note: unbalanced stack on purpose */
36376 
36377  return 1;
36378 }
36379 
36380 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_context *ctx, duk_bool_t nonbmp) {
36381  duk_hthread *thr = (duk_hthread *) ctx;
36382  duk_bufwriter_ctx bw_alloc;
36383  duk_bufwriter_ctx *bw;
36384  duk_idx_t i, n;
36385  duk_ucodepoint_t cp;
36386 
36387  /* XXX: It would be nice to build the string directly but ToUint16()
36388  * coercion is needed so a generic helper would not be very
36389  * helpful (perhaps coerce the value stack first here and then
36390  * build a string from a duk_tval number sequence in one go?).
36391  */
36392 
36393  n = duk_get_top(ctx);
36394 
36395  bw = &bw_alloc;
36396  DUK_BW_INIT_PUSHBUF(thr, bw, n); /* initial estimate for ASCII only codepoints */
36397 
36398  for (i = 0; i < n; i++) {
36399  /* XXX: could improve bufwriter handling to write multiple codepoints
36400  * with one ensure call but the relative benefit would be quite small.
36401  */
36402 
36403  if (nonbmp) {
36404  /* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
36405  * (2) cp >= 0 and cp <= 0x10ffff. This check does not
36406  * implement the steps exactly but the outcome should be
36407  * the same.
36408  */
36409  duk_int32_t i32 = 0;
36410  if (!duk_is_whole_get_int32(duk_to_number(ctx, i), &i32) ||
36411  i32 < 0 || i32 > 0x10ffffL) {
36412  DUK_DCERROR_RANGE_INVALID_ARGS((duk_hthread *) ctx);
36413  }
36414  DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
36415  cp = (duk_ucodepoint_t) i32;
36416  DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
36417  } else {
36418 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
36419  /* ToUint16() coercion is mandatory in the E5.1 specification, but
36420  * this non-compliant behavior makes more sense because we support
36421  * non-BMP codepoints. Don't use CESU-8 because that'd create
36422  * surrogate pairs.
36423  */
36424  cp = (duk_ucodepoint_t) duk_to_uint32(ctx, i);
36425  DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
36426 #else
36427  cp = (duk_ucodepoint_t) duk_to_uint16(ctx, i);
36428  DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
36429  DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
36430 #endif
36431  }
36432  }
36433 
36434  DUK_BW_COMPACT(thr, bw);
36435  (void) duk_buffer_to_string(ctx, -1); /* Safe, extended UTF-8 or CESU-8 encoded. */
36436  return 1;
36437 }
36438 
36439 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx) {
36440  return duk__construct_from_codepoints(ctx, 0 /*nonbmp*/);
36441 }
36442 
36443 #if defined(DUK_USE_ES6)
36444 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx) {
36445  return duk__construct_from_codepoints(ctx, 1 /*nonbmp*/);
36446 }
36447 #endif
36448 
36449 /*
36450  * toString(), valueOf()
36451  */
36452 
36453 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx) {
36454  duk_tval *tv;
36455 
36456  duk_push_this(ctx);
36457  tv = duk_require_tval(ctx, -1);
36458  DUK_ASSERT(tv != NULL);
36459 
36460  if (DUK_TVAL_IS_STRING(tv)) {
36461  /* return as is */
36462  } else if (DUK_TVAL_IS_OBJECT(tv)) {
36463  duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
36464  DUK_ASSERT(h != NULL);
36465 
36466  /* Must be a "string object", i.e. class "String" */
36467  if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
36468  goto type_error;
36469  }
36470 
36471  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VALUE);
36472  DUK_ASSERT(duk_is_string(ctx, -1));
36473  } else {
36474  goto type_error;
36475  }
36476 
36477  (void) duk_require_hstring_notsymbol(ctx, -1); /* Reject symbols (and wrapped symbols). */
36478  return 1;
36479 
36480  type_error:
36481  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
36482 }
36483 
36484 /*
36485  * Character and charcode access
36486  */
36487 
36488 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx) {
36489  duk_int_t pos;
36490 
36491  /* XXX: faster implementation */
36492 
36493  (void) duk_push_this_coercible_to_string(ctx);
36494  pos = duk_to_int(ctx, 0);
36495  duk_substring(ctx, -1, pos, pos + 1);
36496  return 1;
36497 }
36498 
36499 /* Magic: 0=charCodeAt, 1=codePointAt */
36500 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx) {
36501  duk_hthread *thr = (duk_hthread *) ctx;
36502  duk_int_t pos;
36503  duk_hstring *h;
36504  duk_bool_t clamped;
36505  duk_uint32_t cp;
36506  duk_int_t magic;
36507 
36508  /* XXX: faster implementation */
36509 
36510  DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(ctx, 0)));
36511 
36512  h = duk_push_this_coercible_to_string(ctx);
36513  DUK_ASSERT(h != NULL);
36514 
36515  pos = duk_to_int_clamped_raw(ctx,
36516  0 /*index*/,
36517  0 /*min(incl)*/,
36518  DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
36519  &clamped /*out_clamped*/);
36520 #if defined(DUK_USE_ES6)
36521  magic = duk_get_current_magic(ctx);
36522 #else
36523  DUK_ASSERT(duk_get_current_magic(ctx) == 0);
36524  magic = 0;
36525 #endif
36526  if (clamped) {
36527  /* For out-of-bounds indices .charCodeAt() returns NaN and
36528  * .codePointAt() returns undefined.
36529  */
36530  if (magic != 0) {
36531  return 0;
36532  }
36533  duk_push_nan(ctx);
36534  } else {
36535  cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, pos, (duk_bool_t) magic /*surrogate_aware*/);
36536  duk_push_u32(ctx, cp);
36537  }
36538  return 1;
36539 }
36540 
36541 /*
36542  * substring(), substr(), slice()
36543  */
36544 
36545 /* XXX: any chance of merging these three similar but still slightly
36546  * different algorithms so that footprint would be reduced?
36547  */
36548 
36549 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx) {
36550  duk_hstring *h;
36551  duk_int_t start_pos, end_pos;
36552  duk_int_t len;
36553 
36554  h = duk_push_this_coercible_to_string(ctx);
36555  DUK_ASSERT(h != NULL);
36556  len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
36557 
36558  /* [ start end str ] */
36559 
36560  start_pos = duk_to_int_clamped(ctx, 0, 0, len);
36561  if (duk_is_undefined(ctx, 1)) {
36562  end_pos = len;
36563  } else {
36564  end_pos = duk_to_int_clamped(ctx, 1, 0, len);
36565  }
36566  DUK_ASSERT(start_pos >= 0 && start_pos <= len);
36567  DUK_ASSERT(end_pos >= 0 && end_pos <= len);
36568 
36569  if (start_pos > end_pos) {
36570  duk_int_t tmp = start_pos;
36571  start_pos = end_pos;
36572  end_pos = tmp;
36573  }
36574 
36575  DUK_ASSERT(end_pos >= start_pos);
36576 
36577  duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
36578  return 1;
36579 }
36580 
36581 #if defined(DUK_USE_SECTION_B)
36582 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx) {
36583  duk_hstring *h;
36584  duk_int_t start_pos, end_pos;
36585  duk_int_t len;
36586 
36587  /* Unlike non-obsolete String calls, substr() algorithm in E5.1
36588  * specification will happily coerce undefined and null to strings
36589  * ("undefined" and "null").
36590  */
36591  duk_push_this(ctx);
36592  h = duk_to_hstring_m1(ctx); /* Reject Symbols. */
36593  DUK_ASSERT(h != NULL);
36594  len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
36595 
36596  /* [ start length str ] */
36597 
36598  /* The implementation for computing of start_pos and end_pos differs
36599  * from the standard algorithm, but is intended to result in the exactly
36600  * same behavior. This is not always obvious.
36601  */
36602 
36603  /* combines steps 2 and 5; -len ensures max() not needed for step 5 */
36604  start_pos = duk_to_int_clamped(ctx, 0, -len, len);
36605  if (start_pos < 0) {
36606  start_pos = len + start_pos;
36607  }
36608  DUK_ASSERT(start_pos >= 0 && start_pos <= len);
36609 
36610  /* combines steps 3, 6; step 7 is not needed */
36611  if (duk_is_undefined(ctx, 1)) {
36612  end_pos = len;
36613  } else {
36614  DUK_ASSERT(start_pos <= len);
36615  end_pos = start_pos + duk_to_int_clamped(ctx, 1, 0, len - start_pos);
36616  }
36617  DUK_ASSERT(start_pos >= 0 && start_pos <= len);
36618  DUK_ASSERT(end_pos >= 0 && end_pos <= len);
36619  DUK_ASSERT(end_pos >= start_pos);
36620 
36621  duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
36622  return 1;
36623 }
36624 #endif /* DUK_USE_SECTION_B */
36625 
36626 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx) {
36627  duk_hstring *h;
36628  duk_int_t start_pos, end_pos;
36629  duk_int_t len;
36630 
36631  h = duk_push_this_coercible_to_string(ctx);
36632  DUK_ASSERT(h != NULL);
36633  len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
36634 
36635  /* [ start end str ] */
36636 
36637  start_pos = duk_to_int_clamped(ctx, 0, -len, len);
36638  if (start_pos < 0) {
36639  start_pos = len + start_pos;
36640  }
36641  if (duk_is_undefined(ctx, 1)) {
36642  end_pos = len;
36643  } else {
36644  end_pos = duk_to_int_clamped(ctx, 1, -len, len);
36645  if (end_pos < 0) {
36646  end_pos = len + end_pos;
36647  }
36648  }
36649  DUK_ASSERT(start_pos >= 0 && start_pos <= len);
36650  DUK_ASSERT(end_pos >= 0 && end_pos <= len);
36651 
36652  if (end_pos < start_pos) {
36653  end_pos = start_pos;
36654  }
36655 
36656  DUK_ASSERT(end_pos >= start_pos);
36657 
36658  duk_substring(ctx, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
36659  return 1;
36660 }
36661 
36662 /*
36663  * Case conversion
36664  */
36665 
36666 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx) {
36667  duk_hthread *thr = (duk_hthread *) ctx;
36668  duk_small_int_t uppercase = duk_get_current_magic(ctx);
36669 
36670  (void) duk_push_this_coercible_to_string(ctx);
36671  duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
36672  return 1;
36673 }
36674 
36675 /*
36676  * indexOf() and lastIndexOf()
36677  */
36678 
36679 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx) {
36680  duk_hthread *thr = (duk_hthread *) ctx;
36681  duk_hstring *h_this;
36682  duk_hstring *h_search;
36683  duk_int_t clen_this;
36684  duk_int_t cpos;
36685  duk_int_t bpos;
36686  const duk_uint8_t *p_start, *p_end, *p;
36687  const duk_uint8_t *q_start;
36688  duk_int_t q_blen;
36689  duk_uint8_t firstbyte;
36690  duk_uint8_t t;
36691  duk_small_int_t is_lastindexof = duk_get_current_magic(ctx); /* 0=indexOf, 1=lastIndexOf */
36692 
36693  h_this = duk_push_this_coercible_to_string(ctx);
36694  DUK_ASSERT(h_this != NULL);
36695  clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
36696 
36697  h_search = duk_to_hstring(ctx, 0);
36698  DUK_ASSERT(h_search != NULL);
36699  q_start = DUK_HSTRING_GET_DATA(h_search);
36700  q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
36701 
36702  duk_to_number(ctx, 1);
36703  if (duk_is_nan(ctx, 1) && is_lastindexof) {
36704  /* indexOf: NaN should cause pos to be zero.
36705  * lastIndexOf: NaN should cause pos to be +Infinity
36706  * (and later be clamped to len).
36707  */
36708  cpos = clen_this;
36709  } else {
36710  cpos = duk_to_int_clamped(ctx, 1, 0, clen_this);
36711  }
36712 
36713  /* Empty searchstring always matches; cpos must be clamped here.
36714  * (If q_blen were < 0 due to clamped coercion, it would also be
36715  * caught here.)
36716  */
36717  if (q_blen <= 0) {
36718  duk_push_int(ctx, cpos);
36719  return 1;
36720  }
36721  DUK_ASSERT(q_blen > 0);
36722 
36723  bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
36724 
36725  p_start = DUK_HSTRING_GET_DATA(h_this);
36726  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
36727  p = p_start + bpos;
36728 
36729  /* This loop is optimized for size. For speed, there should be
36730  * two separate loops, and we should ensure that memcmp() can be
36731  * used without an extra "will searchstring fit" check. Doing
36732  * the preconditioning for 'p' and 'p_end' is easy but cpos
36733  * must be updated if 'p' is wound back (backward scanning).
36734  */
36735 
36736  firstbyte = q_start[0]; /* leading byte of match string */
36737  while (p <= p_end && p >= p_start) {
36738  t = *p;
36739 
36740  /* For Ecmascript strings, this check can only match for
36741  * initial UTF-8 bytes (not continuation bytes). For other
36742  * strings all bets are off.
36743  */
36744 
36745  if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
36746  DUK_ASSERT(q_blen > 0); /* no issues with memcmp() zero size, even if broken */
36747  if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
36748  duk_push_int(ctx, cpos);
36749  return 1;
36750  }
36751  }
36752 
36753  /* track cpos while scanning */
36754  if (is_lastindexof) {
36755  /* when going backwards, we decrement cpos 'early';
36756  * 'p' may point to a continuation byte of the char
36757  * at offset 'cpos', but that's OK because we'll
36758  * backtrack all the way to the initial byte.
36759  */
36760  if ((t & 0xc0) != 0x80) {
36761  cpos--;
36762  }
36763  p--;
36764  } else {
36765  if ((t & 0xc0) != 0x80) {
36766  cpos++;
36767  }
36768  p++;
36769  }
36770  }
36771 
36772  /* Not found. Empty string case is handled specially above. */
36773  duk_push_int(ctx, -1);
36774  return 1;
36775 }
36776 
36777 /*
36778  * replace()
36779  */
36780 
36781 /* XXX: the current implementation works but is quite clunky; it compiles
36782  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
36783  * shared helpers, etc). Some ideas for refactoring:
36784  *
36785  * - a primitive to convert a string into a regexp matcher (reduces matching
36786  * code at the cost of making matching much slower)
36787  * - use replace() as a basic helper for match() and split(), which are both
36788  * much simpler
36789  * - API call to get_prop and to_boolean
36790  */
36791 
36792 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx) {
36793  duk_hthread *thr = (duk_hthread *) ctx;
36794  duk_hstring *h_input;
36795  duk_hstring *h_match;
36796  duk_hstring *h_search;
36797  duk_hobject *h_re;
36798  duk_bufwriter_ctx bw_alloc;
36799  duk_bufwriter_ctx *bw;
36800 #if defined(DUK_USE_REGEXP_SUPPORT)
36801  duk_bool_t is_regexp;
36802  duk_bool_t is_global;
36803 #endif
36804  duk_bool_t is_repl_func;
36805  duk_uint32_t match_start_coff, match_start_boff;
36806 #if defined(DUK_USE_REGEXP_SUPPORT)
36807  duk_int_t match_caps;
36808 #endif
36809  duk_uint32_t prev_match_end_boff;
36810  const duk_uint8_t *r_start, *r_end, *r; /* repl string scan */
36811  duk_size_t tmp_sz;
36812 
36813  DUK_ASSERT_TOP(ctx, 2);
36814  h_input = duk_push_this_coercible_to_string(ctx);
36815  DUK_ASSERT(h_input != NULL);
36816 
36817  bw = &bw_alloc;
36818  DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input)); /* input size is good output starting point */
36819 
36820  DUK_ASSERT_TOP(ctx, 4);
36821 
36822  /* stack[0] = search value
36823  * stack[1] = replace value
36824  * stack[2] = input string
36825  * stack[3] = result buffer
36826  */
36827 
36828  h_re = duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP);
36829  if (h_re) {
36830 #if defined(DUK_USE_REGEXP_SUPPORT)
36831  is_regexp = 1;
36832  is_global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
36833 
36834  if (is_global) {
36835  /* start match from beginning */
36836  duk_push_int(ctx, 0);
36837  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
36838  }
36839 #else /* DUK_USE_REGEXP_SUPPORT */
36840  DUK_DCERROR_UNSUPPORTED(thr);
36841 #endif /* DUK_USE_REGEXP_SUPPORT */
36842  } else {
36843  duk_to_string(ctx, 0); /* rejects symbols */
36844 #if defined(DUK_USE_REGEXP_SUPPORT)
36845  is_regexp = 0;
36846  is_global = 0;
36847 #endif
36848  }
36849 
36850  if (duk_is_function(ctx, 1)) {
36851  is_repl_func = 1;
36852  r_start = NULL;
36853  r_end = NULL;
36854  } else {
36855  duk_hstring *h_repl;
36856 
36857  is_repl_func = 0;
36858  h_repl = duk_to_hstring(ctx, 1); /* reject symbols */
36859  DUK_ASSERT(h_repl != NULL);
36860  r_start = DUK_HSTRING_GET_DATA(h_repl);
36861  r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
36862  }
36863 
36864  prev_match_end_boff = 0;
36865 
36866  for (;;) {
36867  /*
36868  * If matching with a regexp:
36869  * - non-global RegExp: lastIndex not touched on a match, zeroed
36870  * on a non-match
36871  * - global RegExp: on match, lastIndex will be updated by regexp
36872  * executor to point to next char after the matching part (so that
36873  * characters in the matching part are not matched again)
36874  *
36875  * If matching with a string:
36876  * - always non-global match, find first occurrence
36877  *
36878  * We need:
36879  * - The character offset of start-of-match for the replacer function
36880  * - The byte offsets for start-of-match and end-of-match to implement
36881  * the replacement values $&, $`, and $', and to copy non-matching
36882  * input string portions (including header and trailer) verbatim.
36883  *
36884  * NOTE: the E5.1 specification is a bit vague how the RegExp should
36885  * behave in the replacement process; e.g. is matching done first for
36886  * all matches (in the global RegExp case) before any replacer calls
36887  * are made? See: test-bi-string-proto-replace.js for discussion.
36888  */
36889 
36890  DUK_ASSERT_TOP(ctx, 4);
36891 
36892 #if defined(DUK_USE_REGEXP_SUPPORT)
36893  if (is_regexp) {
36894  duk_dup_0(ctx);
36895  duk_dup_2(ctx);
36896  duk_regexp_match(thr); /* [ ... regexp input ] -> [ res_obj ] */
36897  if (!duk_is_object(ctx, -1)) {
36898  duk_pop(ctx);
36899  break;
36900  }
36901 
36902  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INDEX);
36903  DUK_ASSERT(duk_is_number(ctx, -1));
36904  match_start_coff = duk_get_int(ctx, -1);
36905  duk_pop(ctx);
36906 
36907  duk_get_prop_index(ctx, -1, 0);
36908  DUK_ASSERT(duk_is_string(ctx, -1));
36909  h_match = duk_known_hstring(ctx, -1);
36910  duk_pop(ctx); /* h_match is borrowed, remains reachable through match_obj */
36911 
36912  if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
36913  /* This should be equivalent to match() algorithm step 8.f.iii.2:
36914  * detect an empty match and allow it, but don't allow it twice.
36915  */
36916  duk_uint32_t last_index;
36917 
36918  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
36919  last_index = (duk_uint32_t) duk_get_uint(ctx, -1);
36920  DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
36921  (long) last_index, (long) (last_index + 1)));
36922  duk_pop(ctx);
36923  duk_push_int(ctx, last_index + 1);
36924  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
36925  }
36926 
36927  DUK_ASSERT(duk_get_length(ctx, -1) <= DUK_INT_MAX); /* string limits */
36928  match_caps = (duk_int_t) duk_get_length(ctx, -1);
36929  } else {
36930 #else /* DUK_USE_REGEXP_SUPPORT */
36931  { /* unconditionally */
36932 #endif /* DUK_USE_REGEXP_SUPPORT */
36933  const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
36934  const duk_uint8_t *q_start; /* match string */
36935  duk_size_t q_blen;
36936 
36937 #if defined(DUK_USE_REGEXP_SUPPORT)
36938  DUK_ASSERT(!is_global); /* single match always */
36939 #endif
36940 
36941  p_start = DUK_HSTRING_GET_DATA(h_input);
36942  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
36943  p = p_start;
36944 
36945  h_search = duk_known_hstring(ctx, 0);
36946  q_start = DUK_HSTRING_GET_DATA(h_search);
36947  q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
36948 
36949  p_end -= q_blen; /* ensure full memcmp() fits in while */
36950 
36951  match_start_coff = 0;
36952 
36953  while (p <= p_end) {
36954  DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
36955  if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
36956  duk_dup_0(ctx);
36957  h_match = duk_known_hstring(ctx, -1);
36958 #if defined(DUK_USE_REGEXP_SUPPORT)
36959  match_caps = 0;
36960 #endif
36961  goto found;
36962  }
36963 
36964  /* track utf-8 non-continuation bytes */
36965  if ((p[0] & 0xc0) != 0x80) {
36966  match_start_coff++;
36967  }
36968  p++;
36969  }
36970 
36971  /* not found */
36972  break;
36973  }
36974  found:
36975 
36976  /* stack[0] = search value
36977  * stack[1] = replace value
36978  * stack[2] = input string
36979  * stack[3] = result buffer
36980  * stack[4] = regexp match OR match string
36981  */
36982 
36983  match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
36984 
36985  tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
36986  DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
36987 
36988  prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
36989 
36990  if (is_repl_func) {
36991  duk_idx_t idx_args;
36992  duk_hstring *h_repl;
36993 
36994  /* regexp res_obj is at index 4 */
36995 
36996  duk_dup_1(ctx);
36997  idx_args = duk_get_top(ctx);
36998 
36999 #if defined(DUK_USE_REGEXP_SUPPORT)
37000  if (is_regexp) {
37001  duk_int_t idx;
37002  duk_require_stack(ctx, match_caps + 2);
37003  for (idx = 0; idx < match_caps; idx++) {
37004  /* match followed by capture(s) */
37005  duk_get_prop_index(ctx, 4, idx);
37006  }
37007  } else {
37008 #else /* DUK_USE_REGEXP_SUPPORT */
37009  { /* unconditionally */
37010 #endif /* DUK_USE_REGEXP_SUPPORT */
37011  /* match == search string, by definition */
37012  duk_dup_0(ctx);
37013  }
37014  duk_push_int(ctx, match_start_coff);
37015  duk_dup_2(ctx);
37016 
37017  /* [ ... replacer match [captures] match_char_offset input ] */
37018 
37019  duk_call(ctx, duk_get_top(ctx) - idx_args);
37020  h_repl = duk_to_hstring_m1(ctx); /* -> [ ... repl_value ] */
37021  DUK_ASSERT(h_repl != NULL);
37022 
37023  DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
37024 
37025  duk_pop(ctx); /* repl_value */
37026  } else {
37027  r = r_start;
37028 
37029  while (r < r_end) {
37030  duk_int_t ch1;
37031  duk_int_t ch2;
37032 #if defined(DUK_USE_REGEXP_SUPPORT)
37033  duk_int_t ch3;
37034 #endif
37035  duk_size_t left;
37036 
37037  ch1 = *r++;
37038  if (ch1 != DUK_ASC_DOLLAR) {
37039  goto repl_write;
37040  }
37041  left = r_end - r;
37042 
37043  if (left <= 0) {
37044  goto repl_write;
37045  }
37046 
37047  ch2 = r[0];
37048  switch (ch2) {
37049  case DUK_ASC_DOLLAR: {
37050  ch1 = (1 << 8) + DUK_ASC_DOLLAR;
37051  goto repl_write;
37052  }
37053  case DUK_ASC_AMP: {
37054  DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
37055  r++;
37056  continue;
37057  }
37058  case DUK_ASC_GRAVE: {
37059  tmp_sz = (duk_size_t) match_start_boff;
37060  DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
37061  r++;
37062  continue;
37063  }
37064  case DUK_ASC_SINGLEQUOTE: {
37065  duk_uint32_t match_end_boff;
37066 
37067  /* Use match charlen instead of bytelen, just in case the input and
37068  * match codepoint encodings would have different lengths.
37069  */
37070  match_end_boff = duk_heap_strcache_offset_char2byte(thr,
37071  h_input,
37072  match_start_coff + DUK_HSTRING_GET_CHARLEN(h_match));
37073 
37074  tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
37075  DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
37076  r++;
37077  continue;
37078  }
37079  default: {
37080 #if defined(DUK_USE_REGEXP_SUPPORT)
37081  duk_int_t capnum, captmp, capadv;
37082  /* XXX: optional check, match_caps is zero if no regexp,
37083  * so dollar will be interpreted literally anyway.
37084  */
37085 
37086  if (!is_regexp) {
37087  goto repl_write;
37088  }
37089 
37090  if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
37091  goto repl_write;
37092  }
37093  capnum = ch2 - DUK_ASC_0;
37094  capadv = 1;
37095 
37096  if (left >= 2) {
37097  ch3 = r[1];
37098  if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
37099  captmp = capnum * 10 + (ch3 - DUK_ASC_0);
37100  if (captmp < match_caps) {
37101  capnum = captmp;
37102  capadv = 2;
37103  }
37104  }
37105  }
37106 
37107  if (capnum > 0 && capnum < match_caps) {
37108  DUK_ASSERT(is_regexp != 0); /* match_caps == 0 without regexps */
37109 
37110  /* regexp res_obj is at offset 4 */
37111  duk_get_prop_index(ctx, 4, (duk_uarridx_t) capnum);
37112  if (duk_is_string(ctx, -1)) {
37113  duk_hstring *h_tmp_str;
37114 
37115  h_tmp_str = duk_known_hstring(ctx, -1);
37116 
37117  DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
37118  } else {
37119  /* undefined -> skip (replaced with empty) */
37120  }
37121  duk_pop(ctx);
37122  r += capadv;
37123  continue;
37124  } else {
37125  goto repl_write;
37126  }
37127 #else /* DUK_USE_REGEXP_SUPPORT */
37128  goto repl_write; /* unconditionally */
37129 #endif /* DUK_USE_REGEXP_SUPPORT */
37130  } /* default case */
37131  } /* switch (ch2) */
37132 
37133  repl_write:
37134  /* ch1 = (r_increment << 8) + byte */
37135 
37136  DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
37137  r += ch1 >> 8;
37138  } /* while repl */
37139  } /* if (is_repl_func) */
37140 
37141  duk_pop(ctx); /* pop regexp res_obj or match string */
37142 
37143 #if defined(DUK_USE_REGEXP_SUPPORT)
37144  if (!is_global) {
37145 #else
37146  { /* unconditionally; is_global==0 */
37147 #endif
37148  break;
37149  }
37150  }
37151 
37152  /* trailer */
37153  tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
37154  DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
37155 
37156  DUK_ASSERT_TOP(ctx, 4);
37157  DUK_BW_COMPACT(thr, bw);
37158  (void) duk_buffer_to_string(ctx, -1); /* Safe if inputs are safe. */
37159  return 1;
37160 }
37161 
37162 /*
37163  * split()
37164  */
37165 
37166 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
37167  * used so compiler doesn't complain).
37168  */
37169 
37170 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx) {
37171  duk_hthread *thr = (duk_hthread *) ctx;
37172  duk_hstring *h_input;
37173  duk_hstring *h_sep;
37174  duk_uint32_t limit;
37175  duk_uint32_t arr_idx;
37176 #if defined(DUK_USE_REGEXP_SUPPORT)
37177  duk_bool_t is_regexp;
37178 #endif
37179  duk_bool_t matched; /* set to 1 if any match exists (needed for empty input special case) */
37180  duk_uint32_t prev_match_end_coff, prev_match_end_boff;
37181  duk_uint32_t match_start_boff, match_start_coff;
37182  duk_uint32_t match_end_boff, match_end_coff;
37183 
37184  DUK_UNREF(thr);
37185 
37186  h_input = duk_push_this_coercible_to_string(ctx);
37187  DUK_ASSERT(h_input != NULL);
37188 
37189  duk_push_array(ctx);
37190 
37191  if (duk_is_undefined(ctx, 1)) {
37192  limit = 0xffffffffUL;
37193  } else {
37194  limit = duk_to_uint32(ctx, 1);
37195  }
37196 
37197  if (limit == 0) {
37198  return 1;
37199  }
37200 
37201  /* If the separator is a RegExp, make a "clone" of it. The specification
37202  * algorithm calls [[Match]] directly for specific indices; we emulate this
37203  * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
37204  * which will use global-style matching even when the RegExp itself is non-global.
37205  */
37206 
37207  if (duk_is_undefined(ctx, 0)) {
37208  /* The spec algorithm first does "R = ToString(separator)" before checking
37209  * whether separator is undefined. Since this is side effect free, we can
37210  * skip the ToString() here.
37211  */
37212  duk_dup_2(ctx);
37213  duk_put_prop_index(ctx, 3, 0);
37214  return 1;
37215  } else if (duk_get_hobject_with_class(ctx, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
37216 #if defined(DUK_USE_REGEXP_SUPPORT)
37217  duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
37218  duk_dup_0(ctx);
37219  duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
37220  duk_replace(ctx, 0);
37221  /* lastIndex is initialized to zero by new RegExp() */
37222  is_regexp = 1;
37223 #else
37224  DUK_DCERROR_UNSUPPORTED(thr);
37225 #endif
37226  } else {
37227  duk_to_string(ctx, 0);
37228 #if defined(DUK_USE_REGEXP_SUPPORT)
37229  is_regexp = 0;
37230 #endif
37231  }
37232 
37233  /* stack[0] = separator (string or regexp)
37234  * stack[1] = limit
37235  * stack[2] = input string
37236  * stack[3] = result array
37237  */
37238 
37239  prev_match_end_boff = 0;
37240  prev_match_end_coff = 0;
37241  arr_idx = 0;
37242  matched = 0;
37243 
37244  for (;;) {
37245  /*
37246  * The specification uses RegExp [[Match]] to attempt match at specific
37247  * offsets. We don't have such a primitive, so we use an actual RegExp
37248  * and tweak lastIndex. Since the RegExp may be non-global, we use a
37249  * special variant which forces global-like behavior for matching.
37250  */
37251 
37252  DUK_ASSERT_TOP(ctx, 4);
37253 
37254 #if defined(DUK_USE_REGEXP_SUPPORT)
37255  if (is_regexp) {
37256  duk_dup_0(ctx);
37257  duk_dup_2(ctx);
37258  duk_regexp_match_force_global(thr); /* [ ... regexp input ] -> [ res_obj ] */
37259  if (!duk_is_object(ctx, -1)) {
37260  duk_pop(ctx);
37261  break;
37262  }
37263  matched = 1;
37264 
37265  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INDEX);
37266  DUK_ASSERT(duk_is_number(ctx, -1));
37267  match_start_coff = duk_get_int(ctx, -1);
37268  match_start_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
37269  duk_pop(ctx);
37270 
37271  if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
37272  /* don't allow an empty match at the end of the string */
37273  duk_pop(ctx);
37274  break;
37275  }
37276 
37277  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
37278  DUK_ASSERT(duk_is_number(ctx, -1));
37279  match_end_coff = duk_get_int(ctx, -1);
37280  match_end_boff = duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
37281  duk_pop(ctx);
37282 
37283  /* empty match -> bump and continue */
37284  if (prev_match_end_boff == match_end_boff) {
37285  duk_push_int(ctx, match_end_coff + 1);
37286  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
37287  duk_pop(ctx);
37288  continue;
37289  }
37290  } else {
37291 #else /* DUK_USE_REGEXP_SUPPORT */
37292  { /* unconditionally */
37293 #endif /* DUK_USE_REGEXP_SUPPORT */
37294  const duk_uint8_t *p_start, *p_end, *p; /* input string scan */
37295  const duk_uint8_t *q_start; /* match string */
37296  duk_size_t q_blen, q_clen;
37297 
37298  p_start = DUK_HSTRING_GET_DATA(h_input);
37299  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
37300  p = p_start + prev_match_end_boff;
37301 
37302  h_sep = duk_known_hstring(ctx, 0); /* symbol already rejected above */
37303  q_start = DUK_HSTRING_GET_DATA(h_sep);
37304  q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
37305  q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
37306 
37307  p_end -= q_blen; /* ensure full memcmp() fits in while */
37308 
37309  match_start_coff = prev_match_end_coff;
37310 
37311  if (q_blen == 0) {
37312  /* Handle empty separator case: it will always match, and always
37313  * triggers the check in step 13.c.iii initially. Note that we
37314  * must skip to either end of string or start of first codepoint,
37315  * skipping over any continuation bytes!
37316  *
37317  * Don't allow an empty string to match at the end of the input.
37318  */
37319 
37320  matched = 1; /* empty separator can always match */
37321 
37322  match_start_coff++;
37323  p++;
37324  while (p < p_end) {
37325  if ((p[0] & 0xc0) != 0x80) {
37326  goto found;
37327  }
37328  p++;
37329  }
37330  goto not_found;
37331  }
37332 
37333  DUK_ASSERT(q_blen > 0 && q_clen > 0);
37334  while (p <= p_end) {
37335  DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
37336  DUK_ASSERT(q_blen > 0); /* no issues with empty memcmp() */
37337  if (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
37338  /* never an empty match, so step 13.c.iii can't be triggered */
37339  goto found;
37340  }
37341 
37342  /* track utf-8 non-continuation bytes */
37343  if ((p[0] & 0xc0) != 0x80) {
37344  match_start_coff++;
37345  }
37346  p++;
37347  }
37348 
37349  not_found:
37350  /* not found */
37351  break;
37352 
37353  found:
37354  matched = 1;
37355  match_start_boff = (duk_uint32_t) (p - p_start);
37356  match_end_coff = (duk_uint32_t) (match_start_coff + q_clen); /* constrained by string length */
37357  match_end_boff = (duk_uint32_t) (match_start_boff + q_blen); /* ditto */
37358 
37359  /* empty match (may happen with empty separator) -> bump and continue */
37360  if (prev_match_end_boff == match_end_boff) {
37361  prev_match_end_boff++;
37362  prev_match_end_coff++;
37363  continue;
37364  }
37365  } /* if (is_regexp) */
37366 
37367  /* stack[0] = separator (string or regexp)
37368  * stack[1] = limit
37369  * stack[2] = input string
37370  * stack[3] = result array
37371  * stack[4] = regexp res_obj (if is_regexp)
37372  */
37373 
37374  DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
37375  (long) match_start_boff, (long) match_start_coff,
37376  (long) match_end_boff, (long) match_end_coff,
37377  (long) prev_match_end_boff, (long) prev_match_end_coff));
37378 
37379  duk_push_lstring(ctx,
37380  (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
37381  (duk_size_t) (match_start_boff - prev_match_end_boff));
37382  duk_put_prop_index(ctx, 3, arr_idx);
37383  arr_idx++;
37384  if (arr_idx >= limit) {
37385  goto hit_limit;
37386  }
37387 
37388 #if defined(DUK_USE_REGEXP_SUPPORT)
37389  if (is_regexp) {
37390  duk_size_t i, len;
37391 
37392  len = duk_get_length(ctx, 4);
37393  for (i = 1; i < len; i++) {
37394  DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* cannot have >4G captures */
37395  duk_get_prop_index(ctx, 4, (duk_uarridx_t) i);
37396  duk_put_prop_index(ctx, 3, arr_idx);
37397  arr_idx++;
37398  if (arr_idx >= limit) {
37399  goto hit_limit;
37400  }
37401  }
37402 
37403  duk_pop(ctx);
37404  /* lastIndex already set up for next match */
37405  } else {
37406 #else /* DUK_USE_REGEXP_SUPPORT */
37407  { /* unconditionally */
37408 #endif /* DUK_USE_REGEXP_SUPPORT */
37409  /* no action */
37410  }
37411 
37412  prev_match_end_boff = match_end_boff;
37413  prev_match_end_coff = match_end_coff;
37414  continue;
37415  } /* for */
37416 
37417  /* Combined step 11 (empty string special case) and 14-15. */
37418 
37419  DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
37420  (long) prev_match_end_boff, (long) prev_match_end_coff));
37421 
37422  if (DUK_HSTRING_GET_CHARLEN(h_input) > 0 || !matched) {
37423  /* Add trailer if:
37424  * a) non-empty input
37425  * b) empty input and no (zero size) match found (step 11)
37426  */
37427 
37428  duk_push_lstring(ctx,
37429  (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
37430  (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
37431  duk_put_prop_index(ctx, 3, arr_idx);
37432  /* No arr_idx update or limit check */
37433  }
37434 
37435  return 1;
37436 
37437  hit_limit:
37438 #if defined(DUK_USE_REGEXP_SUPPORT)
37439  if (is_regexp) {
37440  duk_pop(ctx);
37441  }
37442 #endif
37443 
37444  return 1;
37445 }
37446 
37447 /*
37448  * Various
37449  */
37450 
37451 #if defined(DUK_USE_REGEXP_SUPPORT)
37452 DUK_LOCAL void duk__to_regexp_helper(duk_context *ctx, duk_idx_t idx, duk_bool_t force_new) {
37453  duk_hobject *h;
37454 
37455  /* Shared helper for match() steps 3-4, search() steps 3-4. */
37456 
37457  DUK_ASSERT(idx >= 0);
37458 
37459  if (force_new) {
37460  goto do_new;
37461  }
37462 
37463  h = duk_get_hobject_with_class(ctx, idx, DUK_HOBJECT_CLASS_REGEXP);
37464  if (!h) {
37465  goto do_new;
37466  }
37467  return;
37468 
37469  do_new:
37470  duk_push_hobject_bidx(ctx, DUK_BIDX_REGEXP_CONSTRUCTOR);
37471  duk_dup(ctx, idx);
37472  duk_new(ctx, 1); /* [ ... RegExp val ] -> [ ... res ] */
37473  duk_replace(ctx, idx);
37474 }
37475 #endif /* DUK_USE_REGEXP_SUPPORT */
37476 
37477 #if defined(DUK_USE_REGEXP_SUPPORT)
37478 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx) {
37479  duk_hthread *thr = (duk_hthread *) ctx;
37480 
37481  /* Easiest way to implement the search required by the specification
37482  * is to do a RegExp test() with lastIndex forced to zero. To avoid
37483  * side effects on the argument, "clone" the RegExp if a RegExp was
37484  * given as input.
37485  *
37486  * The global flag of the RegExp should be ignored; setting lastIndex
37487  * to zero (which happens when "cloning" the RegExp) should have an
37488  * equivalent effect.
37489  */
37490 
37491  DUK_ASSERT_TOP(ctx, 1);
37492  (void) duk_push_this_coercible_to_string(ctx); /* at index 1 */
37493  duk__to_regexp_helper(ctx, 0 /*index*/, 1 /*force_new*/);
37494 
37495  /* stack[0] = regexp
37496  * stack[1] = string
37497  */
37498 
37499  /* Avoid using RegExp.prototype methods, as they're writable and
37500  * configurable and may have been changed.
37501  */
37502 
37503  duk_dup_0(ctx);
37504  duk_dup_1(ctx); /* [ ... re_obj input ] */
37505  duk_regexp_match(thr); /* -> [ ... res_obj ] */
37506 
37507  if (!duk_is_object(ctx, -1)) {
37508  duk_push_int(ctx, -1);
37509  return 1;
37510  }
37511 
37512  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INDEX);
37513  DUK_ASSERT(duk_is_number(ctx, -1));
37514  return 1;
37515 }
37516 #endif /* DUK_USE_REGEXP_SUPPORT */
37517 
37518 #if defined(DUK_USE_REGEXP_SUPPORT)
37519 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx) {
37520  duk_hthread *thr = (duk_hthread *) ctx;
37521  duk_bool_t global;
37522  duk_int_t prev_last_index;
37523  duk_int_t this_index;
37524  duk_int_t arr_idx;
37525 
37526  DUK_ASSERT_TOP(ctx, 1);
37527  (void) duk_push_this_coercible_to_string(ctx);
37528  duk__to_regexp_helper(ctx, 0 /*index*/, 0 /*force_new*/);
37529  global = duk_get_prop_stridx_boolean(ctx, 0, DUK_STRIDX_GLOBAL, NULL);
37530  DUK_ASSERT_TOP(ctx, 2);
37531 
37532  /* stack[0] = regexp
37533  * stack[1] = string
37534  */
37535 
37536  if (!global) {
37537  duk_regexp_match(thr); /* -> [ res_obj ] */
37538  return 1; /* return 'res_obj' */
37539  }
37540 
37541  /* Global case is more complex. */
37542 
37543  /* [ regexp string ] */
37544 
37545  duk_push_int(ctx, 0);
37546  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
37547  duk_push_array(ctx);
37548 
37549  /* [ regexp string res_arr ] */
37550 
37551  prev_last_index = 0;
37552  arr_idx = 0;
37553 
37554  for (;;) {
37555  DUK_ASSERT_TOP(ctx, 3);
37556 
37557  duk_dup_0(ctx);
37558  duk_dup_1(ctx);
37559  duk_regexp_match(thr); /* -> [ ... regexp string ] -> [ ... res_obj ] */
37560 
37561  if (!duk_is_object(ctx, -1)) {
37562  duk_pop(ctx);
37563  break;
37564  }
37565 
37566  duk_get_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
37567  DUK_ASSERT(duk_is_number(ctx, -1));
37568  this_index = duk_get_int(ctx, -1);
37569  duk_pop(ctx);
37570 
37571  if (this_index == prev_last_index) {
37572  this_index++;
37573  duk_push_int(ctx, this_index);
37574  duk_put_prop_stridx_short(ctx, 0, DUK_STRIDX_LAST_INDEX);
37575  }
37576  prev_last_index = this_index;
37577 
37578  duk_get_prop_index(ctx, -1, 0); /* match string */
37579  duk_put_prop_index(ctx, 2, arr_idx);
37580  arr_idx++;
37581  duk_pop(ctx); /* res_obj */
37582  }
37583 
37584  if (arr_idx == 0) {
37585  duk_push_null(ctx);
37586  }
37587 
37588  return 1; /* return 'res_arr' or 'null' */
37589 }
37590 #endif /* DUK_USE_REGEXP_SUPPORT */
37591 
37592 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx) {
37593  /* duk_concat() coerces arguments with ToString() in correct order */
37594  (void) duk_push_this_coercible_to_string(ctx);
37595  duk_insert(ctx, 0); /* this is relatively expensive */
37596  duk_concat(ctx, duk_get_top(ctx));
37597  return 1;
37598 }
37599 
37600 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx) {
37601  DUK_ASSERT_TOP(ctx, 0);
37602  (void) duk_push_this_coercible_to_string(ctx);
37603  duk_trim(ctx, 0);
37604  DUK_ASSERT_TOP(ctx, 1);
37605  return 1;
37606 }
37607 
37608 #if defined(DUK_USE_ES6)
37609 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx) {
37610  duk_hstring *h_input;
37611  duk_size_t input_blen;
37612  duk_size_t result_len;
37613  duk_int_t count_signed;
37614  duk_uint_t count;
37615  const duk_uint8_t *src;
37616  duk_uint8_t *buf;
37617  duk_uint8_t *p;
37618  duk_double_t d;
37619 #if !defined(DUK_USE_PREFER_SIZE)
37620  duk_size_t copy_size;
37621  duk_uint8_t *p_end;
37622 #endif
37623 
37624  DUK_ASSERT_TOP(ctx, 1);
37625  h_input = duk_push_this_coercible_to_string(ctx);
37626  DUK_ASSERT(h_input != NULL);
37627  input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
37628 
37629  /* Count is ToNumber() coerced; +Infinity must be always rejected
37630  * (even if input string is zero length), as well as negative values
37631  * and -Infinity. -Infinity doesn't require an explicit check
37632  * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
37633  * as a negative value (regardless of input string length).
37634  */
37635  d = duk_to_number(ctx, 0);
37636  if (duk_double_is_posinf(d)) {
37637  goto fail_range;
37638  }
37639  count_signed = duk_get_int(ctx, 0);
37640  if (count_signed < 0) {
37641  goto fail_range;
37642  }
37643  count = (duk_uint_t) count_signed;
37644 
37645  /* Overflow check for result length. */
37646  result_len = count * input_blen;
37647  if (count != 0 && result_len / count != input_blen) {
37648  goto fail_range;
37649  }
37650 
37651  /* Temporary fixed buffer, later converted to string. */
37652  buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, result_len);
37653  src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
37654 
37655 #if defined(DUK_USE_PREFER_SIZE)
37656  p = buf;
37657  while (count-- > 0) {
37658  DUK_MEMCPY((void *) p, (const void *) src, input_blen); /* copy size may be zero */
37659  p += input_blen;
37660  }
37661 #else /* DUK_USE_PREFER_SIZE */
37662  /* Take advantage of already copied pieces to speed up the process
37663  * especially for small repeated strings.
37664  */
37665  p = buf;
37666  p_end = p + result_len;
37667  copy_size = input_blen;
37668  for (;;) {
37669  duk_size_t remain = (duk_size_t) (p_end - p);
37670  DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
37671  (long) remain, (long) copy_size, (long) input_blen,
37672  (long) result_len));
37673  if (remain <= copy_size) {
37674  /* If result_len is zero, this case is taken and does
37675  * a zero size copy.
37676  */
37677  DUK_MEMCPY((void *) p, (const void *) src, remain);
37678  break;
37679  } else {
37680  DUK_MEMCPY((void *) p, (const void *) src, copy_size);
37681  p += copy_size;
37682  copy_size *= 2;
37683  }
37684 
37685  src = (const duk_uint8_t *) buf; /* Use buf as source for larger copies. */
37686  }
37687 #endif /* DUK_USE_PREFER_SIZE */
37688 
37689  /* XXX: It would be useful to be able to create a duk_hstring with
37690  * a certain byte size whose data area wasn't initialized and which
37691  * wasn't in the string table yet. This would allow a string to be
37692  * constructed directly without a buffer temporary and when it was
37693  * finished, it could be injected into the string table. Currently
37694  * this isn't possible because duk_hstrings are only tracked by the
37695  * intern table (they are not in heap_allocated).
37696  */
37697 
37698  duk_buffer_to_string(ctx, -1); /* Safe if input is safe. */
37699  return 1;
37700 
37701  fail_range:
37702  DUK_DCERROR_RANGE_INVALID_ARGS((duk_hthread *) ctx);
37703 }
37704 #endif /* DUK_USE_ES6 */
37705 
37706 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx) {
37707  duk_hstring *h1;
37708  duk_hstring *h2;
37709  duk_size_t h1_len, h2_len, prefix_len;
37710  duk_small_int_t ret = 0;
37711  duk_small_int_t rc;
37712 
37713  /* The current implementation of localeCompare() is simply a codepoint
37714  * by codepoint comparison, implemented with a simple string compare
37715  * because UTF-8 should preserve codepoint ordering (assuming valid
37716  * shortest UTF-8 encoding).
37717  *
37718  * The specification requires that the return value must be related
37719  * to the sort order: e.g. negative means that 'this' comes before
37720  * 'that' in sort order. We assume an ascending sort order.
37721  */
37722 
37723  /* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
37724 
37725  h1 = duk_push_this_coercible_to_string(ctx);
37726  DUK_ASSERT(h1 != NULL);
37727 
37728  h2 = duk_to_hstring(ctx, 0);
37729  DUK_ASSERT(h2 != NULL);
37730 
37731  h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
37732  h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
37733  prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
37734 
37735  /* Zero size compare not an issue with DUK_MEMCMP. */
37736  rc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),
37737  (const void *) DUK_HSTRING_GET_DATA(h2),
37738  (size_t) prefix_len);
37739 
37740  if (rc < 0) {
37741  ret = -1;
37742  goto done;
37743  } else if (rc > 0) {
37744  ret = 1;
37745  goto done;
37746  }
37747 
37748  /* prefix matches, lengths matter now */
37749  if (h1_len > h2_len) {
37750  ret = 1;
37751  goto done;
37752  } else if (h1_len == h2_len) {
37753  DUK_ASSERT(ret == 0);
37754  goto done;
37755  }
37756  ret = -1;
37757  goto done;
37758 
37759  done:
37760  duk_push_int(ctx, (duk_int_t) ret);
37761  return 1;
37762 }
37763 
37764 #endif /* DUK_USE_STRING_BUILTIN */
37765 /*
37766  * Symbol built-in
37767  */
37768 
37769 /* #include duk_internal.h -> already included */
37770 
37771 #if defined(DUK_USE_SYMBOL_BUILTIN)
37772 
37773 /*
37774  * Constructor
37775  */
37776 
37777 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_context *ctx) {
37778  duk_hthread *thr;
37779  const duk_uint8_t *desc;
37780  duk_size_t len;
37781  duk_uint8_t *buf;
37782  duk_uint8_t *p;
37783  duk_int_t magic;
37784 
37785  thr = (duk_hthread *) ctx;
37786 
37787  magic = duk_get_current_magic(ctx);
37788  if (duk_is_undefined(ctx, 0) && (magic == 0)) {
37789  /* Symbol() accepts undefined and empty string, but they are
37790  * treated differently.
37791  */
37792  desc = NULL;
37793  len = 0;
37794  } else {
37795  /* Symbol.for() coerces undefined to 'undefined' */
37796  desc = (const duk_uint8_t *) duk_to_lstring(ctx, 0, &len);
37797  }
37798 
37799  /* Maximum symbol data length:
37800  * +1 initial byte (0x80 or 0x81)
37801  * +len description
37802  * +1 0xff after description, before unique suffix
37803  * +17 autogenerated unique suffix: 'ffffffff-ffffffff' is longest
37804  * +1 0xff after unique suffix for symbols with undefined description
37805  */
37806  buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, 1 + len + 1 + 17 + 1);
37807  p = buf + 1;
37808  DUK_ASSERT(desc != NULL || len == 0); /* may be NULL if len is 0 */
37809  DUK_MEMCPY((void *) p, (const void *) desc, len);
37810  p += len;
37811  if (magic == 0) {
37812  /* Symbol(): create unique symbol. Use two 32-bit values
37813  * to avoid dependency on 64-bit types and 64-bit integer
37814  * formatting (at least for now).
37815  */
37816  if (++thr->heap->sym_counter[0] == 0) {
37817  thr->heap->sym_counter[1]++;
37818  }
37819  p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
37820  (unsigned long) thr->heap->sym_counter[1],
37821  (unsigned long) thr->heap->sym_counter[0]);
37822  if (desc == NULL) {
37823  /* Special case for 'undefined' description, trailing
37824  * 0xff distinguishes from empty string description,
37825  * but needs minimal special case handling elsewhere.
37826  */
37827  *p++ = 0xff;
37828  }
37829  buf[0] = 0x81;
37830  } else {
37831  /* Symbol.for(): create a global symbol */
37832  buf[0] = 0x80;
37833  }
37834 
37835  duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
37836  DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(ctx, -1)));
37837  return 1;
37838 }
37839 
37840 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_context *ctx, duk_tval *tv_arg) {
37841  duk_tval *tv;
37842  duk_tval tv_val;
37843  duk_hobject *h_obj;
37844  duk_hstring *h_str;
37845 
37846  DUK_ASSERT(tv_arg != NULL);
37847 
37848  /* XXX: add internal helper: duk_auto_unbox_tval(ctx, tv, mask); */
37849  /* XXX: add internal helper: duk_auto_unbox(ctx, tv, idx); */
37850 
37851  tv = tv_arg;
37852  if (DUK_TVAL_IS_OBJECT(tv)) {
37853  h_obj = DUK_TVAL_GET_OBJECT(tv);
37854  DUK_ASSERT(h_obj != NULL);
37855  if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
37856  if (!duk_hobject_get_internal_value(((duk_hthread *) ctx)->heap, h_obj, &tv_val)) {
37857  return NULL;
37858  }
37859  tv = &tv_val;
37860  } else {
37861  return NULL;
37862  }
37863  }
37864 
37865  if (!DUK_TVAL_IS_STRING(tv)) {
37866  return NULL;
37867  }
37868  h_str = DUK_TVAL_GET_STRING(tv);
37869  DUK_ASSERT(h_str != NULL);
37870 
37871  if (!DUK_HSTRING_HAS_SYMBOL(h_str)) {
37872  return NULL;
37873  }
37874 
37875  return h_str;
37876 }
37877 
37878 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_context *ctx) {
37879  duk_hstring *h_str;
37880 
37881  h_str = duk__auto_unbox_symbol(ctx, DUK_HTHREAD_THIS_PTR((duk_hthread *) ctx));
37882  if (h_str == NULL) {
37883  return DUK_RET_TYPE_ERROR;
37884  }
37885 
37886  if (duk_get_current_magic(ctx) == 0) {
37887  /* .toString() */
37888  duk_push_symbol_descriptive_string(ctx, h_str);
37889  } else {
37890  /* .valueOf() */
37891  }
37892  return 1;
37893 }
37894 
37895 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_context *ctx) {
37896  duk_hstring *h;
37897  const duk_uint8_t *p;
37898 
37899  /* Argument must be a symbol but not checked here. The initial byte
37900  * check will catch non-symbol strings.
37901  */
37902  h = duk_require_hstring(ctx, 0);
37903  DUK_ASSERT(h != NULL);
37904 
37905  p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
37906  DUK_ASSERT(p != NULL);
37907 
37908  /* Even for zero length strings there's at least one NUL byte so
37909  * we can safely check the initial byte.
37910  */
37911  if (p[0] == 0x80) {
37912  /* Global symbol, return its key (bytes just after the initial byte). */
37913  duk_push_lstring(ctx, (const char *) (p + 1), DUK_HSTRING_GET_BYTELEN(h) - 1);
37914  return 1;
37915  } else if (p[0] == 0x81 || p[0] == 0xff) {
37916  /* Local symbol or hidden symbol, return undefined. */
37917  return 0;
37918  }
37919 
37920  /* Covers normal strings and unknown initial bytes. */
37921  return DUK_RET_TYPE_ERROR;
37922 }
37923 
37924 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_context *ctx) {
37925  duk_hstring *h_str;
37926 
37927  h_str = duk__auto_unbox_symbol(ctx, DUK_HTHREAD_THIS_PTR((duk_hthread *) ctx));
37928  if (h_str == NULL) {
37929  return DUK_RET_TYPE_ERROR;
37930  }
37931  duk_push_hstring(ctx, h_str);
37932  return 1;
37933 }
37934 
37935 #endif /* DUK_USE_SYMBOL_BUILTIN */
37936 /*
37937  * Thread builtins
37938  */
37939 
37940 /* #include duk_internal.h -> already included */
37941 
37942 /*
37943  * Constructor
37944  */
37945 
37946 #if defined(DUK_USE_COROUTINE_SUPPORT)
37947 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_context *ctx) {
37948  duk_hthread *new_thr;
37949  duk_hobject *func;
37950 
37951  /* Check that the argument is callable; this is not 100% because we
37952  * don't allow native functions to be a thread's initial function.
37953  * Resume will reject such functions in any case.
37954  */
37955  /* XXX: need a duk_require_func_promote_lfunc() */
37956  func = duk_require_hobject_promote_lfunc(ctx, 0);
37957  DUK_ASSERT(func != NULL);
37958  duk_require_callable(ctx, 0);
37959 
37960  duk_push_thread(ctx);
37961  new_thr = (duk_hthread *) duk_known_hobject(ctx, -1);
37962  new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
37963 
37964  /* push initial function call to new thread stack; this is
37965  * picked up by resume().
37966  */
37967  duk_push_hobject((duk_context *) new_thr, func);
37968 
37969  return 1; /* return thread */
37970 }
37971 #endif
37972 
37973 /*
37974  * Resume a thread.
37975  *
37976  * The thread must be in resumable state, either (a) new thread which hasn't
37977  * yet started, or (b) a thread which has previously yielded. This method
37978  * must be called from an Ecmascript function.
37979  *
37980  * Args:
37981  * - thread
37982  * - value
37983  * - isError (defaults to false)
37984  *
37985  * Note: yield and resume handling is currently asymmetric.
37986  */
37987 
37988 #if defined(DUK_USE_COROUTINE_SUPPORT)
37989 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
37990  duk_hthread *thr = (duk_hthread *) ctx;
37991  duk_hthread *thr_resume;
37992  duk_hobject *caller_func;
37993  duk_small_int_t is_error;
37994 
37995  DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
37996  (duk_tval *) duk_get_tval(ctx, 0),
37997  (duk_tval *) duk_get_tval(ctx, 1),
37998  (duk_tval *) duk_get_tval(ctx, 2)));
37999 
38000  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
38001  DUK_ASSERT(thr->heap->curr_thread == thr);
38002 
38003  thr_resume = duk_require_hthread(ctx, 0);
38004  is_error = (duk_small_int_t) duk_to_boolean(ctx, 2);
38005  duk_set_top(ctx, 2);
38006 
38007  /* [ thread value ] */
38008 
38009  /*
38010  * Thread state and calling context checks
38011  */
38012 
38013  if (thr->callstack_top < 2) {
38014  DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
38015  goto state_error;
38016  }
38017  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
38018  DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
38019  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
38020 
38021  caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
38022  if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
38023  DUK_DD(DUK_DDPRINT("resume state invalid: caller must be Ecmascript code"));
38024  goto state_error;
38025  }
38026 
38027  /* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
38028  * like for yield.
38029  */
38030 
38031  if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
38032  thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
38033  DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
38034  goto state_error;
38035  }
38036 
38037  DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
38038  thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
38039 
38040  /* Further state-dependent pre-checks */
38041 
38042  if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
38043  /* no pre-checks now, assume a previous yield() has left things in
38044  * tip-top shape (longjmp handler will assert for these).
38045  */
38046  } else {
38047  duk_hobject *h_fun;
38048 
38049  DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
38050 
38051  /* The initial function must be an Ecmascript function (but
38052  * can be bound). We must make sure of that before we longjmp
38053  * because an error in the RESUME handler call processing will
38054  * not be handled very cleanly.
38055  */
38056  if ((thr_resume->callstack_top != 0) ||
38057  (thr_resume->valstack_top - thr_resume->valstack != 1)) {
38058  goto state_error;
38059  }
38060 
38061  duk_push_tval(ctx, DUK_GET_TVAL_NEGIDX((duk_context *) thr_resume, -1));
38062  duk_resolve_nonbound_function(ctx);
38063  h_fun = duk_require_hobject(ctx, -1); /* reject lightfuncs on purpose */
38064  if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
38065  goto state_error;
38066  }
38067  duk_pop(ctx);
38068  }
38069 
38070  /*
38071  * The error object has been augmented with a traceback and other
38072  * info from its creation point -- usually another thread. The
38073  * error handler is called here right before throwing, but it also
38074  * runs in the resumer's thread. It might be nice to get a traceback
38075  * from the resumee but this is not the case now.
38076  */
38077 
38078 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
38079  if (is_error) {
38080  DUK_ASSERT_TOP(ctx, 2); /* value (error) is at stack top */
38081  duk_err_augment_error_throw(thr); /* in resumer's context */
38082  }
38083 #endif
38084 
38085 #if defined(DUK_USE_DEBUG)
38086  if (is_error) {
38087  DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
38088  (duk_tval *) duk_get_tval(ctx, 0),
38089  (duk_tval *) duk_get_tval(ctx, 1)));
38090  } else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
38091  DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
38092  (duk_tval *) duk_get_tval(ctx, 0),
38093  (duk_tval *) duk_get_tval(ctx, 1)));
38094  } else {
38095  DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
38096  (duk_tval *) duk_get_tval(ctx, 0),
38097  (duk_tval *) duk_get_tval(ctx, 1)));
38098  }
38099 #endif
38100 
38101  thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
38102 
38103  /* lj value2: thread */
38104  DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
38105  DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]); /* side effects */
38106 
38107  /* lj value1: value */
38108  DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
38109  DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
38110  DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
38111 
38112  thr->heap->lj.iserror = is_error;
38113 
38114  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
38115  duk_err_longjmp(thr); /* execution resumes in bytecode executor */
38116  DUK_UNREACHABLE();
38117  /* Never here, fall through to error (from compiler point of view). */
38118 
38119  state_error:
38120  DUK_DCERROR_TYPE_INVALID_STATE(thr);
38121 }
38122 #endif
38123 
38124 /*
38125  * Yield the current thread.
38126  *
38127  * The thread must be in yieldable state: it must have a resumer, and there
38128  * must not be any yield-preventing calls (native calls and constructor calls,
38129  * currently) in the thread's call stack (otherwise a resume would not be
38130  * possible later). This method must be called from an Ecmascript function.
38131  *
38132  * Args:
38133  * - value
38134  * - isError (defaults to false)
38135  *
38136  * Note: yield and resume handling is currently asymmetric.
38137  */
38138 
38139 #if defined(DUK_USE_COROUTINE_SUPPORT)
38140 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
38141  duk_hthread *thr = (duk_hthread *) ctx;
38142  duk_hobject *caller_func;
38143  duk_small_int_t is_error;
38144 
38145  DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
38146  (duk_tval *) duk_get_tval(ctx, 0),
38147  (duk_tval *) duk_get_tval(ctx, 1)));
38148 
38149  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
38150  DUK_ASSERT(thr->heap->curr_thread == thr);
38151 
38152  is_error = (duk_small_int_t) duk_to_boolean(ctx, 1);
38153  duk_set_top(ctx, 1);
38154 
38155  /* [ value ] */
38156 
38157  /*
38158  * Thread state and calling context checks
38159  */
38160 
38161  if (!thr->resumer) {
38162  DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
38163  goto state_error;
38164  }
38165  DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
38166 
38167  if (thr->callstack_top < 2) {
38168  DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
38169  goto state_error;
38170  }
38171  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL); /* us */
38172  DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
38173  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL); /* caller */
38174 
38175  caller_func = DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2);
38176  if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
38177  DUK_DD(DUK_DDPRINT("yield state invalid: caller must be Ecmascript code"));
38178  goto state_error;
38179  }
38180 
38181  DUK_ASSERT(thr->callstack_preventcount >= 1); /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
38182  if (thr->callstack_preventcount != 1) {
38183  /* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
38184  DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
38185  (long) thr->callstack_preventcount));
38186  goto state_error;
38187  }
38188 
38189  /*
38190  * The error object has been augmented with a traceback and other
38191  * info from its creation point -- usually the current thread.
38192  * The error handler, however, is called right before throwing
38193  * and runs in the yielder's thread.
38194  */
38195 
38196 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
38197  if (is_error) {
38198  DUK_ASSERT_TOP(ctx, 1); /* value (error) is at stack top */
38199  duk_err_augment_error_throw(thr); /* in yielder's context */
38200  }
38201 #endif
38202 
38203 #if defined(DUK_USE_DEBUG)
38204  if (is_error) {
38205  DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
38206  (duk_tval *) duk_get_tval(ctx, 0)));
38207  } else {
38208  DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
38209  (duk_tval *) duk_get_tval(ctx, 0)));
38210  }
38211 #endif
38212 
38213  /*
38214  * Process yield
38215  *
38216  * After longjmp(), processing continues in bytecode executor longjmp
38217  * handler, which will e.g. update thr->resumer to NULL.
38218  */
38219 
38220  thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
38221 
38222  /* lj value1: value */
38223  DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
38224  DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
38225  DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
38226 
38227  thr->heap->lj.iserror = is_error;
38228 
38229  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* call is from executor, so we know we have a jmpbuf */
38230  duk_err_longjmp(thr); /* execution resumes in bytecode executor */
38231  DUK_UNREACHABLE();
38232  /* Never here, fall through to error (from compiler point of view). */
38233 
38234  state_error:
38235  DUK_DCERROR_TYPE_INVALID_STATE(thr);
38236 }
38237 #endif
38238 
38239 #if defined(DUK_USE_COROUTINE_SUPPORT)
38240 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_context *ctx) {
38241  duk_push_current_thread(ctx);
38242  return 1;
38243 }
38244 #endif
38245 /*
38246  * Type error thrower, E5 Section 13.2.3.
38247  */
38248 
38249 /* #include duk_internal.h -> already included */
38250 
38251 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx) {
38252  DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
38253 }
38254 /*
38255  * Fixed buffer helper useful for debugging, requires no allocation
38256  * which is critical for debugging.
38257  */
38258 
38259 /* #include duk_internal.h -> already included */
38260 
38261 #if defined(DUK_USE_DEBUG)
38262 
38263 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
38264  duk_size_t avail;
38265  duk_size_t copylen;
38266 
38267  avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
38268  if (length > avail) {
38269  copylen = avail;
38270  fb->truncated = 1;
38271  } else {
38272  copylen = length;
38273  }
38274  DUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);
38275  fb->offset += copylen;
38276 }
38277 
38278 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
38279  duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
38280 }
38281 
38282 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
38283  duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
38284 }
38285 
38286 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
38287  duk_size_t avail;
38288  va_list ap;
38289 
38290  va_start(ap, fmt);
38291  avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
38292  if (avail > 0) {
38293  duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
38294  if (res < 0) {
38295  /* error */
38296  } else if ((duk_size_t) res >= avail) {
38297  /* (maybe) truncated */
38298  fb->offset += avail;
38299  if ((duk_size_t) res > avail) {
38300  /* actual chars dropped (not just NUL term) */
38301  fb->truncated = 1;
38302  }
38303  } else {
38304  /* normal */
38305  fb->offset += res;
38306  }
38307  }
38308  va_end(ap);
38309 }
38310 
38311 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
38312  char buf[64+1];
38313  duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
38314  buf[sizeof(buf) - 1] = (char) 0;
38315  duk_fb_put_cstring(fb, buf);
38316 }
38317 
38318 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
38319  return (fb->offset >= fb->length);
38320 }
38321 
38322 #endif /* DUK_USE_DEBUG */
38323 /*
38324  * Custom formatter for debug printing, allowing Duktape specific data
38325  * structures (such as tagged values and heap objects) to be printed with
38326  * a nice format string. Because debug printing should not affect execution
38327  * state, formatting here must be independent of execution (see implications
38328  * below) and must not allocate memory.
38329  *
38330  * Custom format tags begin with a '%!' to safely distinguish them from
38331  * standard format tags. The following conversions are supported:
38332  *
38333  * %!T tagged value (duk_tval *)
38334  * %!O heap object (duk_heaphdr *)
38335  * %!I decoded bytecode instruction
38336  * %!C bytecode instruction opcode name (arg is long)
38337  *
38338  * Everything is serialized in a JSON-like manner. The default depth is one
38339  * level, internal prototype is not followed, and internal properties are not
38340  * serialized. The following modifiers change this behavior:
38341  *
38342  * @ print pointers
38343  * # print binary representations (where applicable)
38344  * d deep traversal of own properties (not prototype)
38345  * p follow prototype chain (useless without 'd')
38346  * i include internal properties (other than prototype)
38347  * x hexdump buffers
38348  * h heavy formatting
38349  *
38350  * For instance, the following serializes objects recursively, but does not
38351  * follow the prototype chain nor print internal properties: "%!dO".
38352  *
38353  * Notes:
38354  *
38355  * * Standard snprintf return value semantics seem to vary. This
38356  * implementation returns the number of bytes it actually wrote
38357  * (excluding the null terminator). If retval == buffer size,
38358  * output was truncated (except for corner cases).
38359  *
38360  * * Output format is intentionally different from Ecmascript
38361  * formatting requirements, as formatting here serves debugging
38362  * of internals.
38363  *
38364  * * Depth checking (and updating) is done in each type printer
38365  * separately, to allow them to call each other freely.
38366  *
38367  * * Some pathological structures might take ages to print (e.g.
38368  * self recursion with 100 properties pointing to the object
38369  * itself). To guard against these, each printer also checks
38370  * whether the output buffer is full; if so, early exit.
38371  *
38372  * * Reference loops are detected using a loop stack.
38373  */
38374 
38375 /* #include duk_internal.h -> already included */
38376 
38377 #if defined(DUK_USE_DEBUG)
38378 
38379 /* #include stdio.h -> already included */
38380 /* #include stdarg.h -> already included */
38381 #include <string.h>
38382 
38383 /* list of conversion specifiers that terminate a format tag;
38384  * this is unfortunately guesswork.
38385  */
38386 #define DUK__ALLOWED_STANDARD_SPECIFIERS "diouxXeEfFgGaAcsCSpnm"
38387 
38388 /* maximum length of standard format tag that we support */
38389 #define DUK__MAX_FORMAT_TAG_LENGTH 32
38390 
38391 /* heapobj recursion depth when deep printing is selected */
38392 #define DUK__DEEP_DEPTH_LIMIT 8
38393 
38394 /* maximum recursion depth for loop detection stacks */
38395 #define DUK__LOOP_STACK_DEPTH 256
38396 
38397 /* must match bytecode defines now; build autogenerate? */
38398 DUK_LOCAL const char *duk__bc_optab[256] = {
38399  "LDREG", "STREG", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF", "LDNULL",
38400  "LDTRUE", "LDFALSE", "BNOT", "LNOT", "UNM", "UNP", "TYPEOF", "TYPEOFID",
38401  "EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
38402  "SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
38403 
38404  "GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
38405  "LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
38406  "IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
38407  "SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
38408 
38409  "DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
38410  "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC", "BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC",
38411  "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC", "BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC",
38412  "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC", "BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC",
38413 
38414  "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC", "IN_RR", "IN_CR", "IN_RC", "IN_CC",
38415  "PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
38416  "PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
38417  "POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
38418 
38419  "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC", "PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC",
38420  "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC", "DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC",
38421  "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
38422  "CLOSURE", "GETVAR", "PUTVAR", "DELVAR", "JUMP", "RETREG", "RETUNDEF", "RETCONST",
38423 
38424  "RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
38425  "ENDFIN", "THROW", "CSREG", "EVALCALL", "CALL", "TAILCALL", "NEW", "NEWOBJ",
38426  "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI", "SETALEN",
38427  "INITENUM", "NEXTENUM", "INVLHS", "DEBUGGER", "NOP", "INVALID", "UNUSED190", "UNUSED191",
38428 
38429  "UNUSED192", "UNUSED193", "UNUSED194", "UNUSED195", "UNUSED196", "UNUSED197", "UNUSED198", "UNUSED199",
38430  "UNUSED200", "UNUSED201", "UNUSED202", "UNUSED203", "UNUSED204", "UNUSED205", "UNUSED206", "UNUSED207",
38431  "UNUSED208", "UNUSED209", "UNUSED210", "UNUSED211", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
38432  "UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
38433 
38434  "UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
38435  "UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
38436  "UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
38437  "UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
38438 };
38439 
38440 typedef struct duk__dprint_state duk__dprint_state;
38441 struct duk__dprint_state {
38442  duk_fixedbuffer *fb;
38443 
38444  /* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
38445  * to not couple these two mechanisms unnecessarily.
38446  */
38447  duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
38448  duk_int_t loop_stack_index;
38449  duk_int_t loop_stack_limit;
38450 
38451  duk_int_t depth;
38452  duk_int_t depth_limit;
38453 
38454  duk_bool_t pointer;
38455  duk_bool_t heavy;
38456  duk_bool_t binary;
38457  duk_bool_t follow_proto;
38458  duk_bool_t internal;
38459  duk_bool_t hexdump;
38460 };
38461 
38462 /* helpers */
38463 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
38464 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
38465 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
38466 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
38467 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
38468 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
38469 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
38470 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
38471 
38472 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
38473  duk_fixedbuffer *fb = st->fb;
38474 
38475  if (st->heavy) {
38476  duk_fb_sprintf(fb, "(%p)", (void *) h);
38477  }
38478 
38479  if (!h) {
38480  return;
38481  }
38482 
38483  if (st->binary) {
38484  duk_size_t i;
38485  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
38486  for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
38487  duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
38488  }
38489  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
38490  }
38491 
38492 #if defined(DUK_USE_REFERENCE_COUNTING) /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
38493  if (st->heavy) {
38494  duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
38495  "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
38496  (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
38497  (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
38498  (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
38499  (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
38500  (long) DUK_HEAPHDR_GET_TYPE(h),
38501  (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
38502  (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
38503  (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
38504  (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
38505  }
38506 #else
38507  if (st->heavy) {
38508  duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
38509  (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
38510  (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
38511  (long) DUK_HEAPHDR_GET_TYPE(h),
38512  (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
38513  (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
38514  (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
38515  (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
38516  }
38517 #endif
38518 }
38519 
38520 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
38521  duk_fixedbuffer *fb = st->fb;
38522 
38523  if (st->heavy) {
38524  duk_fb_sprintf(fb, "(%p)", (void *) h);
38525  }
38526 
38527  if (!h) {
38528  return;
38529  }
38530 
38531  if (st->binary) {
38532  duk_size_t i;
38533  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
38534  for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
38535  duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
38536  }
38537  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
38538  }
38539 
38540 #if defined(DUK_USE_REFERENCE_COUNTING)
38541  if (st->heavy) {
38542  duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
38543  (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
38544  (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
38545  (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
38546  (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
38547  (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
38548  (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
38549  (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
38550  }
38551 #else
38552  if (st->heavy) {
38553  duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
38554  (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
38555  (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
38556  (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
38557  (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
38558  (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
38559  (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
38560  }
38561 #endif
38562 }
38563 
38564 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
38565  duk_fixedbuffer *fb = st->fb;
38566  const duk_uint8_t *p;
38567  const duk_uint8_t *p_end;
38568 
38569  /* terminal type: no depth check */
38570 
38571  if (duk_fb_is_full(fb)) {
38572  return;
38573  }
38574 
38575  duk__print_shared_heaphdr_string(st, &h->hdr);
38576 
38577  if (!h) {
38578  duk_fb_put_cstring(fb, "NULL");
38579  return;
38580  }
38581 
38582  p = DUK_HSTRING_GET_DATA(h);
38583  p_end = p + DUK_HSTRING_GET_BYTELEN(h);
38584 
38585  if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
38586  /* if property key begins with underscore, encode it with
38587  * forced quotes (e.g. "_Foo") to distinguish it from encoded
38588  * internal properties (e.g. \xffBar -> _Bar).
38589  */
38590  quotes = 1;
38591  }
38592 
38593  if (quotes) {
38594  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
38595  }
38596  while (p < p_end) {
38597  duk_uint8_t ch = *p++;
38598 
38599  /* two special escapes: '\' and '"', other printables as is */
38600  if (ch == '\\') {
38601  duk_fb_sprintf(fb, "\\\\");
38602  } else if (ch == '"') {
38603  duk_fb_sprintf(fb, "\\\"");
38604  } else if (ch >= 0x20 && ch <= 0x7e) {
38605  duk_fb_put_byte(fb, ch);
38606  } else if (ch == 0xff && !quotes) {
38607  /* encode \xffBar as _Bar if no quotes are applied, this is for
38608  * readable internal keys.
38609  */
38610  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
38611  } else {
38612  duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
38613  }
38614  }
38615  if (quotes) {
38616  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
38617  }
38618 #if defined(DUK_USE_REFERENCE_COUNTING)
38619  /* XXX: limit to quoted strings only, to save keys from being cluttered? */
38620  duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
38621 #endif
38622 }
38623 
38624 #define DUK__COMMA() do { \
38625  if (first) { \
38626  first = 0; \
38627  } else { \
38628  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
38629  } \
38630  } while (0)
38631 
38632 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
38633  duk_fixedbuffer *fb = st->fb;
38634  duk_uint_fast32_t i;
38635  duk_tval *tv;
38636  duk_hstring *key;
38637  duk_bool_t first = 1;
38638  const char *brace1 = "{";
38639  const char *brace2 = "}";
38640  duk_bool_t pushed_loopstack = 0;
38641 
38642  if (duk_fb_is_full(fb)) {
38643  return;
38644  }
38645 
38646  duk__print_shared_heaphdr(st, &h->hdr);
38647 
38648  if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
38649  brace1 = "[";
38650  brace2 = "]";
38651  }
38652 
38653  if (!h) {
38654  duk_fb_put_cstring(fb, "NULL");
38655  goto finished;
38656  }
38657 
38658  if (st->depth >= st->depth_limit) {
38659  const char *subtype = "generic";
38660 
38661  if (DUK_HOBJECT_IS_COMPFUNC(h)) {
38662  subtype = "compfunc";
38663  } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
38664  subtype = "natfunc";
38665  } else if (DUK_HOBJECT_IS_THREAD(h)) {
38666  subtype = "thread";
38667  } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
38668  subtype = "bufobj";
38669  } else if (DUK_HOBJECT_IS_ARRAY(h)) {
38670  subtype = "array";
38671  }
38672  duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
38673  return;
38674  }
38675 
38676  for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
38677  if (st->loop_stack[i] == h) {
38678  duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
38679  return;
38680  }
38681  }
38682 
38683  /* after this, return paths should 'goto finished' for decrement */
38684  st->depth++;
38685 
38686  if (st->loop_stack_index >= st->loop_stack_limit) {
38687  duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
38688  goto finished;
38689  }
38690  st->loop_stack[st->loop_stack_index++] = h;
38691  pushed_loopstack = 1;
38692 
38693  /*
38694  * Notation: double underscore used for internal properties which are not
38695  * stored in the property allocation (e.g. '__valstack').
38696  */
38697 
38698  duk_fb_put_cstring(fb, brace1);
38699 
38700  if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
38701  duk_uint32_t a_limit;
38702 
38703  a_limit = DUK_HOBJECT_GET_ASIZE(h);
38704  if (st->internal) {
38705  /* dump all allocated entries, unused entries print as 'unused',
38706  * note that these may extend beyond current 'length' and look
38707  * a bit funny.
38708  */
38709  } else {
38710  /* leave out trailing 'unused' elements */
38711  while (a_limit > 0) {
38712  tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
38713  if (!DUK_TVAL_IS_UNUSED(tv)) {
38714  break;
38715  }
38716  a_limit--;
38717  }
38718  }
38719 
38720  for (i = 0; i < a_limit; i++) {
38721  tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
38722  DUK__COMMA();
38723  duk__print_tval(st, tv);
38724  }
38725  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
38726  key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
38727  if (!key) {
38728  continue;
38729  }
38730  if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
38731  continue;
38732  }
38733  DUK__COMMA();
38734  duk__print_hstring(st, key, 0);
38735  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
38736  if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
38737  duk_fb_sprintf(fb, "[get:%p,set:%p]",
38738  (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
38739  (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
38740  } else {
38741  tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
38742  duk__print_tval(st, tv);
38743  }
38744  if (st->heavy) {
38745  duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
38746  }
38747  }
38748  }
38749  if (st->internal) {
38750  if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
38751  DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
38752  }
38753  if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
38754  DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
38755  }
38756  if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
38757  DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
38758  }
38759  if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
38760  DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
38761  }
38762  if (DUK_HOBJECT_HAS_NATFUNC(h)) {
38763  DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
38764  }
38765  if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
38766  DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
38767  }
38768  if (DUK_HOBJECT_HAS_THREAD(h)) {
38769  DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
38770  }
38771  if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
38772  DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
38773  }
38774  if (DUK_HOBJECT_HAS_STRICT(h)) {
38775  DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
38776  }
38777  if (DUK_HOBJECT_HAS_NOTAIL(h)) {
38778  DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
38779  }
38780  if (DUK_HOBJECT_HAS_NEWENV(h)) {
38781  DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
38782  }
38783  if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
38784  DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
38785  }
38786  if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
38787  DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
38788  }
38789  if (DUK_HOBJECT_HAS_ENVRECCLOSED(h)) {
38790  DUK__COMMA(); duk_fb_sprintf(fb, "__envrecclosed:true");
38791  }
38792  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
38793  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
38794  }
38795  if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
38796  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
38797  }
38798  if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
38799  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
38800  }
38801  if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(h)) {
38802  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_dukfunc:true");
38803  }
38804  if (DUK_HOBJECT_IS_BUFOBJ(h)) {
38805  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
38806  }
38807  if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
38808  DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
38809  }
38810  }
38811 
38812  if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
38813  duk_harray *a = (duk_harray *) h;
38814  DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
38815  DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
38816  } else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
38817  duk_hcompfunc *f = (duk_hcompfunc *) h;
38818  DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
38819  duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
38820  DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
38821  DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
38822  DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
38823  DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
38824 #if defined(DUK_USE_DEBUGGER_SUPPORT)
38825  DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
38826  DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
38827 #endif
38828  DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
38829  duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
38830  } else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
38831  duk_hnatfunc *f = (duk_hnatfunc *) h;
38832  DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
38833  duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
38834  DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
38835  DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
38836 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38837  } else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
38838  duk_hbufobj *b = (duk_hbufobj *) h;
38839  DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
38840  duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
38841  DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
38842  duk__print_hobject(st, (duk_hobject *) b->buf_prop);
38843  DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
38844  DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
38845  DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
38846  DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
38847 #endif
38848  } else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
38849  duk_hthread *t = (duk_hthread *) h;
38850  DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
38851  DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
38852  DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
38853  DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
38854  DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_max:%ld", (long) t->valstack_max);
38855  DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_max:%ld", (long) t->callstack_max);
38856  DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_max:%ld", (long) t->catchstack_max);
38857  DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
38858  DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
38859  DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
38860  DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
38861  DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack:%p", (void *) t->catchstack);
38862  DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_size:%ld", (long) t->catchstack_size);
38863  DUK__COMMA(); duk_fb_sprintf(fb, "__catchstack_top:%ld", (long) t->catchstack_top);
38864  DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
38865  /* XXX: print built-ins array? */
38866 
38867  }
38868 #if defined(DUK_USE_REFERENCE_COUNTING)
38869  if (st->internal) {
38870  DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
38871  }
38872 #endif
38873  if (st->internal) {
38874  DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
38875  }
38876 
38877  DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h); /* own pointer */
38878 
38879  /* prototype should be last, for readability */
38880  if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
38881  if (st->follow_proto) {
38882  DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
38883  } else {
38884  DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
38885  }
38886  }
38887 
38888  duk_fb_put_cstring(fb, brace2);
38889 
38890 #if defined(DUK_USE_HOBJECT_HASH_PART)
38891  if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
38892  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
38893  for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
38894  duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
38895  if (i > 0) {
38896  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
38897  }
38898  if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
38899  duk_fb_sprintf(fb, "u");
38900  } else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
38901  duk_fb_sprintf(fb, "d");
38902  } else {
38903  duk_fb_sprintf(fb, "%ld", (long) h_idx);
38904  }
38905  }
38906  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
38907  }
38908 #endif
38909 
38910  finished:
38911  st->depth--;
38912  if (pushed_loopstack) {
38913  st->loop_stack_index--;
38914  st->loop_stack[st->loop_stack_index] = NULL;
38915  }
38916 }
38917 
38918 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
38919  duk_fixedbuffer *fb = st->fb;
38920  duk_size_t i, n;
38921  duk_uint8_t *p;
38922 
38923  if (duk_fb_is_full(fb)) {
38924  return;
38925  }
38926 
38927  /* terminal type: no depth check */
38928 
38929  if (!h) {
38930  duk_fb_put_cstring(fb, "NULL");
38931  return;
38932  }
38933 
38934  if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
38935  if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
38937  duk_fb_sprintf(fb, "buffer:external:%p:%ld",
38938  (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
38939  (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
38940  } else {
38942  duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
38943  (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
38944  (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
38945  }
38946  } else {
38947  duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
38948  }
38949 
38950 #if defined(DUK_USE_REFERENCE_COUNTING)
38951  duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
38952 #endif
38953 
38954  if (st->hexdump) {
38955  duk_fb_sprintf(fb, "=[");
38956  n = DUK_HBUFFER_GET_SIZE(h);
38957  p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
38958  for (i = 0; i < n; i++) {
38959  duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
38960  }
38961  duk_fb_sprintf(fb, "]");
38962  }
38963 }
38964 
38965 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
38966  duk_fixedbuffer *fb = st->fb;
38967 
38968  if (duk_fb_is_full(fb)) {
38969  return;
38970  }
38971 
38972  if (!h) {
38973  duk_fb_put_cstring(fb, "NULL");
38974  return;
38975  }
38976 
38977  switch (DUK_HEAPHDR_GET_TYPE(h)) {
38978  case DUK_HTYPE_STRING:
38979  duk__print_hstring(st, (duk_hstring *) h, 1);
38980  break;
38981  case DUK_HTYPE_OBJECT:
38982  duk__print_hobject(st, (duk_hobject *) h);
38983  break;
38984  case DUK_HTYPE_BUFFER:
38985  duk__print_hbuffer(st, (duk_hbuffer *) h);
38986  break;
38987  default:
38988  duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
38989  break;
38990  }
38991 }
38992 
38993 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
38994  duk_fixedbuffer *fb = st->fb;
38995 
38996  if (duk_fb_is_full(fb)) {
38997  return;
38998  }
38999 
39000  /* depth check is done when printing an actual type */
39001 
39002  if (st->heavy) {
39003  duk_fb_sprintf(fb, "(%p)", (void *) tv);
39004  }
39005 
39006  if (!tv) {
39007  duk_fb_put_cstring(fb, "NULL");
39008  return;
39009  }
39010 
39011  if (st->binary) {
39012  duk_size_t i;
39013  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
39014  for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
39015  duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
39016  }
39017  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
39018  }
39019 
39020  if (st->heavy) {
39021  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
39022  }
39023  switch (DUK_TVAL_GET_TAG(tv)) {
39024  case DUK_TAG_UNDEFINED: {
39025  duk_fb_put_cstring(fb, "undefined");
39026  break;
39027  }
39028  case DUK_TAG_UNUSED: {
39029  duk_fb_put_cstring(fb, "unused");
39030  break;
39031  }
39032  case DUK_TAG_NULL: {
39033  duk_fb_put_cstring(fb, "null");
39034  break;
39035  }
39036  case DUK_TAG_BOOLEAN: {
39037  duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
39038  break;
39039  }
39040  case DUK_TAG_STRING: {
39041  /* Note: string is a terminal heap object, so no depth check here */
39042  duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
39043  break;
39044  }
39045  case DUK_TAG_OBJECT: {
39046  duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
39047  break;
39048  }
39049  case DUK_TAG_BUFFER: {
39050  duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
39051  break;
39052  }
39053  case DUK_TAG_POINTER: {
39054  duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
39055  break;
39056  }
39057  case DUK_TAG_LIGHTFUNC: {
39058  duk_c_function func;
39059  duk_small_uint_t lf_flags;
39060 
39061  DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
39062  duk_fb_sprintf(fb, "lightfunc:");
39063  duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
39064  duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
39065  break;
39066  }
39067 #if defined(DUK_USE_FASTINT)
39068  case DUK_TAG_FASTINT:
39069 #endif
39070  default: {
39071  /* IEEE double is approximately 16 decimal digits; print a couple extra */
39072  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
39073  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
39074  duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
39075  break;
39076  }
39077  }
39078  if (st->heavy) {
39079  duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
39080  }
39081 }
39082 
39083 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
39084  duk_fixedbuffer *fb = st->fb;
39085  duk_small_int_t op;
39086  const char *op_name;
39087 
39088  op = (duk_small_int_t) DUK_DEC_OP(ins);
39089  op_name = duk__bc_optab[op];
39090 
39091  /* XXX: option to fix opcode length so it lines up nicely */
39092 
39093  if (op == DUK_OP_JUMP) {
39094  duk_int_t diff1 = DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS; /* from next pc */
39095  duk_int_t diff2 = diff1 + 1; /* from curr pc */
39096 
39097  duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
39098  (const char *) op_name, (long) diff1,
39099  (int) (diff2 >= 0 ? '+' : '-'), /* char format: use int */
39100  (long) (diff2 >= 0 ? diff2 : -diff2));
39101  } else {
39102  duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
39103  (const char *) op_name, (long) DUK_DEC_A(ins),
39104  (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
39105  }
39106 }
39107 
39108 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
39109  duk_fixedbuffer *fb = st->fb;
39110 
39111  if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
39112  duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
39113  } else {
39114  duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
39115  }
39116 }
39117 
39118 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
39119  duk_fixedbuffer fb;
39120  const char *p = format;
39121  const char *p_end = p + DUK_STRLEN(format);
39122  duk_int_t retval;
39123 
39124  DUK_MEMZERO(&fb, sizeof(fb));
39125  fb.buffer = (duk_uint8_t *) str;
39126  fb.length = size;
39127  fb.offset = 0;
39128  fb.truncated = 0;
39129 
39130  while (p < p_end) {
39131  char ch = *p++;
39132  const char *p_begfmt = NULL;
39133  duk_bool_t got_exclamation = 0;
39134  duk_bool_t got_long = 0; /* %lf, %ld etc */
39135  duk__dprint_state st;
39136 
39137  if (ch != DUK_ASC_PERCENT) {
39138  duk_fb_put_byte(&fb, (duk_uint8_t) ch);
39139  continue;
39140  }
39141 
39142  /*
39143  * Format tag parsing. Since we don't understand all the
39144  * possible format tags allowed, we just scan for a terminating
39145  * specifier and keep track of relevant modifiers that we do
39146  * understand. See man 3 printf.
39147  */
39148 
39149  DUK_MEMZERO(&st, sizeof(st));
39150  st.fb = &fb;
39151  st.depth = 0;
39152  st.depth_limit = 1;
39153  st.loop_stack_index = 0;
39154  st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
39155 
39156  p_begfmt = p - 1;
39157  while (p < p_end) {
39158  ch = *p++;
39159 
39160  if (ch == DUK_ASC_STAR) {
39161  /* unsupported: would consume multiple args */
39162  goto error;
39163  } else if (ch == DUK_ASC_PERCENT) {
39164  duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
39165  break;
39166  } else if (ch == DUK_ASC_EXCLAMATION) {
39167  got_exclamation = 1;
39168  } else if (!got_exclamation && ch == DUK_ASC_LC_L) {
39169  got_long = 1;
39170  } else if (got_exclamation && ch == DUK_ASC_LC_D) {
39171  st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
39172  } else if (got_exclamation && ch == DUK_ASC_LC_P) {
39173  st.follow_proto = 1;
39174  } else if (got_exclamation && ch == DUK_ASC_LC_I) {
39175  st.internal = 1;
39176  } else if (got_exclamation && ch == DUK_ASC_LC_X) {
39177  st.hexdump = 1;
39178  } else if (got_exclamation && ch == DUK_ASC_LC_H) {
39179  st.heavy = 1;
39180  } else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
39181  st.pointer = 1;
39182  } else if (got_exclamation && ch == DUK_ASC_HASH) {
39183  st.binary = 1;
39184  } else if (got_exclamation && ch == DUK_ASC_UC_T) {
39185  duk_tval *t = va_arg(ap, duk_tval *);
39186  if (st.pointer && !st.heavy) {
39187  duk_fb_sprintf(&fb, "(%p)", (void *) t);
39188  }
39189  duk__print_tval(&st, t);
39190  break;
39191  } else if (got_exclamation && ch == DUK_ASC_UC_O) {
39192  duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
39193  if (st.pointer && !st.heavy) {
39194  duk_fb_sprintf(&fb, "(%p)", (void *) t);
39195  }
39196  duk__print_heaphdr(&st, t);
39197  break;
39198  } else if (got_exclamation && ch == DUK_ASC_UC_I) {
39199  duk_instr_t t = va_arg(ap, duk_instr_t);
39200  duk__print_instr(&st, t);
39201  break;
39202  } else if (got_exclamation && ch == DUK_ASC_UC_C) {
39203  long t = va_arg(ap, long);
39204  duk__print_opcode(&st, (duk_small_int_t) t);
39205  break;
39206  } else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
39207  char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
39208  duk_size_t fmtlen;
39209 
39210  DUK_ASSERT(p >= p_begfmt);
39211  fmtlen = (duk_size_t) (p - p_begfmt);
39212  if (fmtlen >= sizeof(fmtbuf)) {
39213  /* format is too large, abort */
39214  goto error;
39215  }
39216  DUK_MEMZERO(fmtbuf, sizeof(fmtbuf));
39217  DUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);
39218 
39219  /* assume exactly 1 arg, which is why '*' is forbidden; arg size still
39220  * depends on type though.
39221  */
39222 
39223  if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
39224  /* %f and %lf both consume a 'long' */
39225  double arg = va_arg(ap, double);
39226  duk_fb_sprintf(&fb, fmtbuf, arg);
39227  } else if (ch == DUK_ASC_LC_D && got_long) {
39228  /* %ld */
39229  long arg = va_arg(ap, long);
39230  duk_fb_sprintf(&fb, fmtbuf, arg);
39231  } else if (ch == DUK_ASC_LC_D) {
39232  /* %d; only 16 bits are guaranteed */
39233  int arg = va_arg(ap, int);
39234  duk_fb_sprintf(&fb, fmtbuf, arg);
39235  } else if (ch == DUK_ASC_LC_U && got_long) {
39236  /* %lu */
39237  unsigned long arg = va_arg(ap, unsigned long);
39238  duk_fb_sprintf(&fb, fmtbuf, arg);
39239  } else if (ch == DUK_ASC_LC_U) {
39240  /* %u; only 16 bits are guaranteed */
39241  unsigned int arg = va_arg(ap, unsigned int);
39242  duk_fb_sprintf(&fb, fmtbuf, arg);
39243  } else if (ch == DUK_ASC_LC_X && got_long) {
39244  /* %lx */
39245  unsigned long arg = va_arg(ap, unsigned long);
39246  duk_fb_sprintf(&fb, fmtbuf, arg);
39247  } else if (ch == DUK_ASC_LC_X) {
39248  /* %x; only 16 bits are guaranteed */
39249  unsigned int arg = va_arg(ap, unsigned int);
39250  duk_fb_sprintf(&fb, fmtbuf, arg);
39251  } else if (ch == DUK_ASC_LC_S) {
39252  /* %s */
39253  const char *arg = va_arg(ap, const char *);
39254  if (arg == NULL) {
39255  /* '%s' and NULL is not portable, so special case
39256  * it for debug printing.
39257  */
39258  duk_fb_sprintf(&fb, "NULL");
39259  } else {
39260  duk_fb_sprintf(&fb, fmtbuf, arg);
39261  }
39262  } else if (ch == DUK_ASC_LC_P) {
39263  /* %p */
39264  void *arg = va_arg(ap, void *);
39265  if (arg == NULL) {
39266  /* '%p' and NULL is portable, but special case it
39267  * anyway to get a standard NULL marker in logs.
39268  */
39269  duk_fb_sprintf(&fb, "NULL");
39270  } else {
39271  duk_fb_sprintf(&fb, fmtbuf, arg);
39272  }
39273  } else if (ch == DUK_ASC_LC_C) {
39274  /* '%c', passed concretely as int */
39275  int arg = va_arg(ap, int);
39276  duk_fb_sprintf(&fb, fmtbuf, arg);
39277  } else {
39278  /* Should not happen. */
39279  duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
39280  }
39281  break;
39282  } else {
39283  /* ignore */
39284  }
39285  }
39286  }
39287  goto done;
39288 
39289  error:
39290  duk_fb_put_cstring(&fb, "FMTERR");
39291  /* fall through */
39292 
39293  done:
39294  retval = (duk_int_t) fb.offset;
39295  duk_fb_put_byte(&fb, (duk_uint8_t) 0);
39296 
39297  /* return total chars written excluding terminator */
39298  return retval;
39299 }
39300 
39301 #if 0 /*unused*/
39302 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
39303  duk_int_t retval;
39304  va_list ap;
39305  va_start(ap, format);
39306  retval = duk_debug_vsnprintf(str, size, format, ap);
39307  va_end(ap);
39308  return retval;
39309 }
39310 #endif
39311 
39312 /* Formatting function pointers is tricky: there is no standard pointer for
39313  * function pointers and the size of a function pointer may depend on the
39314  * specific pointer type. This helper formats a function pointer based on
39315  * its memory layout to get something useful on most platforms.
39316  */
39317 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
39318  duk_size_t i;
39319  duk_uint8_t *p = (duk_uint8_t *) buf;
39320  duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
39321 
39322  DUK_MEMZERO(buf, buf_size);
39323 
39324  for (i = 0; i < fptr_size; i++) {
39325  duk_int_t left = (duk_int_t) (p_end - p);
39326  duk_uint8_t ch;
39327  if (left <= 0) {
39328  break;
39329  }
39330 
39331  /* Quite approximate but should be useful for little and big endian. */
39332 #if defined(DUK_USE_INTEGER_BE)
39333  ch = fptr[i];
39334 #else
39335  ch = fptr[fptr_size - 1 - i];
39336 #endif
39337  p += DUK_SNPRINTF((char *) p, left, "%02lx", (unsigned long) ch);
39338  }
39339 }
39340 
39341 #endif /* DUK_USE_DEBUG */
39342 
39343 /* automatic undefs */
39344 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
39345 #undef DUK__COMMA
39346 #undef DUK__DEEP_DEPTH_LIMIT
39347 #undef DUK__LOOP_STACK_DEPTH
39348 #undef DUK__MAX_FORMAT_TAG_LENGTH
39349 /*
39350  * Duktape debugger
39351  */
39352 
39353 /* #include duk_internal.h -> already included */
39354 
39355 #if defined(DUK_USE_DEBUGGER_SUPPORT)
39356 
39357 /*
39358  * Helper structs
39359  */
39360 
39361 typedef union {
39362  void *p;
39363  duk_uint_t b[1];
39364  /* Use b[] to access the size of the union, which is strictly not
39365  * correct. Can't use fixed size unless there's feature detection
39366  * for pointer byte size.
39367  */
39368 } duk__ptr_union;
39369 
39370 /*
39371  * Detach handling
39372  */
39373 
39374 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
39375  /* For now shared handler is fine. */ \
39376  duk__debug_do_detach1((thr)->heap, (reason)); \
39377  } while (0)
39378 
39379 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
39380  /* Can be called multiple times with no harm. Mark the transport
39381  * bad (dbg_read_cb == NULL) and clear state except for the detached
39382  * callback and the udata field. The detached callback is delayed
39383  * to the message loop so that it can be called between messages;
39384  * this avoids corner cases related to immediate debugger reattach
39385  * inside the detached callback.
39386  */
39387 
39388  if (heap->dbg_detaching) {
39389  DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
39390  return;
39391  }
39392 
39393  DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
39394 
39395  heap->dbg_detaching = 1; /* prevent multiple in-progress detaches */
39396 
39397  if (heap->dbg_write_cb != NULL) {
39398  duk_hthread *thr;
39399 
39400  thr = heap->heap_thread;
39401  DUK_ASSERT(thr != NULL);
39402 
39403  duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
39404  duk_debug_write_int(thr, reason);
39405  duk_debug_write_eom(thr);
39406  }
39407 
39408  heap->dbg_read_cb = NULL;
39409  heap->dbg_write_cb = NULL;
39410  heap->dbg_peek_cb = NULL;
39411  heap->dbg_read_flush_cb = NULL;
39412  heap->dbg_write_flush_cb = NULL;
39413  heap->dbg_request_cb = NULL;
39414  /* heap->dbg_detached_cb: keep */
39415  /* heap->dbg_udata: keep */
39416  /* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
39417  DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
39418  heap->dbg_state_dirty = 0;
39419  heap->dbg_force_restart = 0;
39420  heap->dbg_step_type = 0;
39421  heap->dbg_step_thread = NULL;
39422  heap->dbg_step_csindex = 0;
39423  heap->dbg_step_startline = 0;
39424  heap->dbg_have_next_byte = 0;
39425 
39426  /* Ensure there are no stale active breakpoint pointers.
39427  * Breakpoint list is currently kept - we could empty it
39428  * here but we'd need to handle refcounts correctly, and
39429  * we'd need a 'thr' reference for that.
39430  *
39431  * XXX: clear breakpoint on either attach or detach?
39432  */
39433  heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
39434 }
39435 
39436 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
39437  duk_debug_detached_function detached_cb;
39438  void *detached_udata;
39439  duk_hthread *thr;
39440  duk_context *ctx;
39441 
39442  thr = heap->heap_thread;
39443  DUK_ASSERT(thr != NULL);
39444  ctx = (duk_context *) thr;
39445 
39446  /* Safe to call multiple times. */
39447 
39448  detached_cb = heap->dbg_detached_cb;
39449  detached_udata = heap->dbg_udata;
39450  heap->dbg_detached_cb = NULL;
39451  heap->dbg_udata = NULL;
39452 
39453  if (detached_cb) {
39454  /* Careful here: state must be wiped before the call
39455  * so that we can cleanly handle a re-attach from
39456  * inside the callback.
39457  */
39458  DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
39459  detached_cb(ctx, detached_udata);
39460  }
39461 
39462  heap->dbg_detaching = 0;
39463 }
39464 
39465 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
39466  duk__debug_do_detach1(heap, 0);
39467  duk__debug_do_detach2(heap);
39468 }
39469 
39470 /* Called on a read/write error: NULL all callbacks except the detached
39471  * callback so that we never accidentally call them after a read/write
39472  * error has been indicated. This is especially important for the transport
39473  * I/O callbacks to fulfill guaranteed callback semantics.
39474  */
39475 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
39476  duk_heap *heap;
39477  heap = thr->heap;
39478  DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
39479  heap->dbg_read_cb = NULL;
39480  heap->dbg_write_cb = NULL; /* this is especially critical to avoid another write call in detach1() */
39481  heap->dbg_peek_cb = NULL;
39482  heap->dbg_read_flush_cb = NULL;
39483  heap->dbg_write_flush_cb = NULL;
39484  heap->dbg_request_cb = NULL;
39485  /* keep heap->dbg_detached_cb */
39486 }
39487 
39488 /*
39489  * Debug connection peek and flush primitives
39490  */
39491 
39492 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
39493  duk_heap *heap;
39494 
39495  DUK_ASSERT(thr != NULL);
39496  heap = thr->heap;
39497  DUK_ASSERT(heap != NULL);
39498 
39499  if (heap->dbg_read_cb == NULL) {
39500  DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
39501  return 0;
39502  }
39503  if (heap->dbg_peek_cb == NULL) {
39504  DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
39505  return 0;
39506  }
39507 
39508  return (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
39509 }
39510 
39511 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
39512  duk_heap *heap;
39513 
39514  DUK_ASSERT(thr != NULL);
39515  heap = thr->heap;
39516  DUK_ASSERT(heap != NULL);
39517 
39518  if (heap->dbg_read_cb == NULL) {
39519  DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
39520  return;
39521  }
39522  if (heap->dbg_read_flush_cb == NULL) {
39523  DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
39524  return;
39525  }
39526 
39527  heap->dbg_read_flush_cb(heap->dbg_udata);
39528 }
39529 
39530 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
39531  duk_heap *heap;
39532 
39533  DUK_ASSERT(thr != NULL);
39534  heap = thr->heap;
39535  DUK_ASSERT(heap != NULL);
39536 
39537  if (heap->dbg_read_cb == NULL) {
39538  DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
39539  return;
39540  }
39541  if (heap->dbg_write_flush_cb == NULL) {
39542  DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
39543  return;
39544  }
39545 
39546  heap->dbg_write_flush_cb(heap->dbg_udata);
39547 }
39548 
39549 /*
39550  * Debug connection skip primitives
39551  */
39552 
39553 /* Skip fully. */
39554 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
39555  duk_uint8_t dummy[64];
39556  duk_size_t now;
39557 
39558  DUK_ASSERT(thr != NULL);
39559 
39560  while (length > 0) {
39561  now = (length > sizeof(dummy) ? sizeof(dummy) : length);
39562  duk_debug_read_bytes(thr, dummy, now);
39563  length -= now;
39564  }
39565 }
39566 
39567 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
39568  DUK_ASSERT(thr != NULL);
39569 
39570  (void) duk_debug_read_byte(thr);
39571 }
39572 
39573 /*
39574  * Debug connection read primitives
39575  */
39576 
39577 /* Peek ahead in the stream one byte. */
39578 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
39579  /* It is important not to call this if the last byte read was an EOM.
39580  * Reading ahead in this scenario would cause unnecessary blocking if
39581  * another message is not available.
39582  */
39583 
39584  duk_uint8_t x;
39585 
39586  x = duk_debug_read_byte(thr);
39587  thr->heap->dbg_have_next_byte = 1;
39588  thr->heap->dbg_next_byte = x;
39589  return x;
39590 }
39591 
39592 /* Read fully. */
39593 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
39594  duk_heap *heap;
39595  duk_uint8_t *p;
39596  duk_size_t left;
39597  duk_size_t got;
39598 
39599  DUK_ASSERT(thr != NULL);
39600  heap = thr->heap;
39601  DUK_ASSERT(heap != NULL);
39602 
39603  if (heap->dbg_read_cb == NULL) {
39604  DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
39605  goto fail;
39606  }
39607 
39608  /* NOTE: length may be zero */
39609  p = data;
39610  if (length >= 1 && heap->dbg_have_next_byte) {
39611  heap->dbg_have_next_byte = 0;
39612  *p++ = heap->dbg_next_byte;
39613  }
39614  for (;;) {
39615  left = (duk_size_t) ((data + length) - p);
39616  if (left == 0) {
39617  break;
39618  }
39619  DUK_ASSERT(heap->dbg_read_cb != NULL);
39620  DUK_ASSERT(left >= 1);
39621 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
39622  left = 1;
39623 #endif
39624  got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
39625  if (got == 0 || got > left) {
39626  DUK_D(DUK_DPRINT("connection error during read, return zero data"));
39627  duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
39628  DUK__SET_CONN_BROKEN(thr, 1);
39629  goto fail;
39630  }
39631  p += got;
39632  }
39633  return;
39634 
39635  fail:
39636  DUK_MEMZERO((void *) data, (size_t) length);
39637 }
39638 
39639 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
39640  duk_uint8_t x;
39641 
39642  x = 0; /* just in case callback is broken and won't write 'x' */
39643  duk_debug_read_bytes(thr, &x, 1);
39644  return x;
39645 }
39646 
39647 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
39648  duk_uint8_t buf[4];
39649 
39650  DUK_ASSERT(thr != NULL);
39651 
39652  duk_debug_read_bytes(thr, buf, 4);
39653  return ((duk_uint32_t) buf[0] << 24) |
39654  ((duk_uint32_t) buf[1] << 16) |
39655  ((duk_uint32_t) buf[2] << 8) |
39656  (duk_uint32_t) buf[3];
39657 }
39658 
39659 DUK_LOCAL duk_uint32_t duk__debug_read_int32_raw(duk_hthread *thr) {
39660  return (duk_int32_t) duk__debug_read_uint32_raw(thr);
39661 }
39662 
39663 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
39664  duk_uint8_t buf[2];
39665 
39666  DUK_ASSERT(thr != NULL);
39667 
39668  duk_debug_read_bytes(thr, buf, 2);
39669  return ((duk_uint16_t) buf[0] << 8) |
39670  (duk_uint16_t) buf[1];
39671 }
39672 
39673 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
39674  duk_small_uint_t x;
39675  duk_small_uint_t t;
39676 
39677  DUK_ASSERT(thr != NULL);
39678 
39679  x = duk_debug_read_byte(thr);
39680  if (x >= 0xc0) {
39681  t = duk_debug_read_byte(thr);
39682  return (duk_int32_t) (((x - 0xc0) << 8) + t);
39683  } else if (x >= 0x80) {
39684  return (duk_int32_t) (x - 0x80);
39685  } else if (x == DUK_DBG_IB_INT4) {
39686  return (duk_int32_t) duk__debug_read_uint32_raw(thr);
39687  }
39688 
39689  DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
39690  DUK__SET_CONN_BROKEN(thr, 1);
39691  return 0;
39692 }
39693 
39694 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
39695  duk_context *ctx = (duk_context *) thr;
39696  duk_uint8_t buf[31];
39697  duk_uint8_t *p;
39698 
39699  if (len <= sizeof(buf)) {
39700  duk_debug_read_bytes(thr, buf, (duk_size_t) len);
39701  duk_push_lstring(ctx, (const char *) buf, (duk_size_t) len);
39702  } else {
39703  p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); /* zero for paranoia */
39704  DUK_ASSERT(p != NULL);
39705  duk_debug_read_bytes(thr, p, (duk_size_t) len);
39706  (void) duk_buffer_to_string(ctx, -1); /* Safety relies on debug client, which is OK. */
39707  }
39708 
39709  return duk_require_hstring(ctx, -1);
39710 }
39711 
39712 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
39713  duk_context *ctx = (duk_context *) thr;
39714  duk_small_uint_t x;
39715  duk_uint32_t len;
39716 
39717  DUK_ASSERT(thr != NULL);
39718 
39719  x = duk_debug_read_byte(thr);
39720  if (x >= 0x60 && x <= 0x7f) {
39721  /* For short strings, use a fixed temp buffer. */
39722  len = (duk_uint32_t) (x - 0x60);
39723  } else if (x == DUK_DBG_IB_STR2) {
39724  len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
39725  } else if (x == DUK_DBG_IB_STR4) {
39726  len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
39727  } else {
39728  goto fail;
39729  }
39730 
39731  return duk__debug_read_hstring_raw(thr, len);
39732 
39733  fail:
39734  DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
39735  DUK__SET_CONN_BROKEN(thr, 1);
39736  duk_push_hstring_empty(ctx); /* always push some string */
39737  return duk_require_hstring(ctx, -1);
39738 }
39739 
39740 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
39741  duk_context *ctx = (duk_context *) thr;
39742  duk_uint8_t *p;
39743 
39744  p = (duk_uint8_t *) duk_push_fixed_buffer(ctx, (duk_size_t) len); /* zero for paranoia */
39745  DUK_ASSERT(p != NULL);
39746  duk_debug_read_bytes(thr, p, (duk_size_t) len);
39747 
39748  return duk_require_hbuffer(ctx, -1);
39749 }
39750 
39751 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
39752  duk_small_uint_t x;
39753  duk__ptr_union pu;
39754 
39755  DUK_ASSERT(thr != NULL);
39756 
39757  x = duk_debug_read_byte(thr);
39758  if (x != sizeof(pu)) {
39759  goto fail;
39760  }
39761  duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
39762 #if defined(DUK_USE_INTEGER_LE)
39763  duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
39764 #endif
39765  return (void *) pu.p;
39766 
39767  fail:
39768  DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
39769  DUK__SET_CONN_BROKEN(thr, 1);
39770  return (void *) NULL;
39771 }
39772 
39773 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
39774  duk_double_union du;
39775 
39776  DUK_ASSERT(sizeof(du.uc) == 8);
39777  duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
39778  DUK_DBLUNION_DOUBLE_NTOH(&du);
39779  return du.d;
39780 }
39781 
39782 #if 0
39783 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
39784  duk_small_uint_t x;
39785 
39786  DUK_ASSERT(thr != NULL);
39787 
39788  x = duk_debug_read_byte(thr);
39789  if (x != DUK_DBG_IB_HEAPPTR) {
39790  goto fail;
39791  }
39792 
39793  return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
39794 
39795  fail:
39796  DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
39797  DUK__SET_CONN_BROKEN(thr, 1);
39798  return NULL;
39799 }
39800 #endif
39801 
39802 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
39803  duk_small_uint_t x;
39804 
39805  DUK_ASSERT(thr != NULL);
39806 
39807  x = duk_debug_read_byte(thr);
39808  switch (x) {
39809  case DUK_DBG_IB_OBJECT:
39810  case DUK_DBG_IB_POINTER:
39811  case DUK_DBG_IB_HEAPPTR:
39812  /* Accept any pointer-like value; for 'object' dvalue, read
39813  * and ignore the class number.
39814  */
39815  if (x == DUK_DBG_IB_OBJECT) {
39816  duk_debug_skip_byte(thr);
39817  }
39818  break;
39819  default:
39820  goto fail;
39821  }
39822 
39823  return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
39824 
39825  fail:
39826  DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
39827  DUK__SET_CONN_BROKEN(thr, 1);
39828  return NULL;
39829 }
39830 
39831 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
39832  duk_context *ctx = (duk_context *) thr;
39833  duk_uint8_t x;
39834  duk_uint_t t;
39835  duk_uint32_t len;
39836 
39837  DUK_ASSERT(thr != NULL);
39838 
39839  x = duk_debug_read_byte(thr);
39840 
39841  if (x >= 0xc0) {
39842  t = (duk_uint_t) (x - 0xc0);
39843  t = (t << 8) + duk_debug_read_byte(thr);
39844  duk_push_uint(ctx, (duk_uint_t) t);
39845  goto return_ptr;
39846  }
39847  if (x >= 0x80) {
39848  duk_push_uint(ctx, (duk_uint_t) (x - 0x80));
39849  goto return_ptr;
39850  }
39851  if (x >= 0x60) {
39852  len = (duk_uint32_t) (x - 0x60);
39853  duk__debug_read_hstring_raw(thr, len);
39854  goto return_ptr;
39855  }
39856 
39857  switch (x) {
39858  case DUK_DBG_IB_INT4: {
39859  duk_int32_t i = duk__debug_read_int32_raw(thr);
39860  duk_push_i32(ctx, i);
39861  break;
39862  }
39863  case DUK_DBG_IB_STR4: {
39864  len = duk__debug_read_uint32_raw(thr);
39865  duk__debug_read_hstring_raw(thr, len);
39866  break;
39867  }
39868  case DUK_DBG_IB_STR2: {
39869  len = duk__debug_read_uint16_raw(thr);
39870  duk__debug_read_hstring_raw(thr, len);
39871  break;
39872  }
39873  case DUK_DBG_IB_BUF4: {
39874  len = duk__debug_read_uint32_raw(thr);
39875  duk__debug_read_hbuffer_raw(thr, len);
39876  break;
39877  }
39878  case DUK_DBG_IB_BUF2: {
39879  len = duk__debug_read_uint16_raw(thr);
39880  duk__debug_read_hbuffer_raw(thr, len);
39881  break;
39882  }
39883  case DUK_DBG_IB_UNDEFINED: {
39884  duk_push_undefined(ctx);
39885  break;
39886  }
39887  case DUK_DBG_IB_NULL: {
39888  duk_push_null(ctx);
39889  break;
39890  }
39891  case DUK_DBG_IB_TRUE: {
39892  duk_push_true(ctx);
39893  break;
39894  }
39895  case DUK_DBG_IB_FALSE: {
39896  duk_push_false(ctx);
39897  break;
39898  }
39899  case DUK_DBG_IB_NUMBER: {
39900  duk_double_t d;
39901  d = duk__debug_read_double_raw(thr);
39902  duk_push_number(ctx, d);
39903  break;
39904  }
39905  case DUK_DBG_IB_OBJECT: {
39906  duk_heaphdr *h;
39907  duk_debug_skip_byte(thr);
39908  h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
39909  duk_push_heapptr(thr, (void *) h);
39910  break;
39911  }
39912  case DUK_DBG_IB_POINTER: {
39913  void *ptr;
39914  ptr = duk__debug_read_pointer_raw(thr);
39915  duk_push_pointer(thr, ptr);
39916  break;
39917  }
39918  case DUK_DBG_IB_LIGHTFUNC: {
39919  /* XXX: Not needed for now, so not implemented. Note that
39920  * function pointers may have different size/layout than
39921  * a void pointer.
39922  */
39923  DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
39924  goto fail;
39925  }
39926  case DUK_DBG_IB_HEAPPTR: {
39927  duk_heaphdr *h;
39928  h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
39929  duk_push_heapptr(thr, (void *) h);
39930  break;
39931  }
39932  case DUK_DBG_IB_UNUSED: /* unused: not accepted in inbound messages */
39933  default:
39934  goto fail;
39935  }
39936 
39937  return_ptr:
39938  return DUK_GET_TVAL_NEGIDX(thr, -1);
39939 
39940  fail:
39941  DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
39942  DUK__SET_CONN_BROKEN(thr, 1);
39943  return NULL;
39944 }
39945 
39946 /*
39947  * Debug connection write primitives
39948  */
39949 
39950 /* Write fully. */
39951 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
39952  duk_heap *heap;
39953  const duk_uint8_t *p;
39954  duk_size_t left;
39955  duk_size_t got;
39956 
39957  DUK_ASSERT(thr != NULL);
39958  DUK_ASSERT(length == 0 || data != NULL);
39959  heap = thr->heap;
39960  DUK_ASSERT(heap != NULL);
39961 
39962  if (heap->dbg_write_cb == NULL) {
39963  DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
39964  return;
39965  }
39966  if (length == 0) {
39967  /* Avoid doing an actual write callback with length == 0,
39968  * because that's reserved for a write flush.
39969  */
39970  return;
39971  }
39972  DUK_ASSERT(data != NULL);
39973 
39974  p = data;
39975  for (;;) {
39976  left = (duk_size_t) ((data + length) - p);
39977  if (left == 0) {
39978  break;
39979  }
39980  DUK_ASSERT(heap->dbg_write_cb != NULL);
39981  DUK_ASSERT(left >= 1);
39982 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
39983  left = 1;
39984 #endif
39985  got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
39986  if (got == 0 || got > left) {
39987  duk__debug_null_most_callbacks(thr); /* avoid calling write callback in detach1() */
39988  DUK_D(DUK_DPRINT("connection error during write"));
39989  DUK__SET_CONN_BROKEN(thr, 1);
39990  return;
39991  }
39992  p += got;
39993  }
39994 }
39995 
39996 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
39997  duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
39998 }
39999 
40000 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
40001  duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
40002 }
40003 
40004 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
40005  duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
40006 }
40007 
40008 #if defined(DUK_USE_DEBUGGER_INSPECT)
40009 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
40010  duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
40011 }
40012 #endif
40013 
40014 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
40015  duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
40016 }
40017 
40018 /* Write signed 32-bit integer. */
40019 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
40020  duk_uint8_t buf[5];
40021  duk_size_t len;
40022 
40023  DUK_ASSERT(thr != NULL);
40024 
40025  if (x >= 0 && x <= 0x3fL) {
40026  buf[0] = (duk_uint8_t) (0x80 + x);
40027  len = 1;
40028  } else if (x >= 0 && x <= 0x3fffL) {
40029  buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
40030  buf[1] = (duk_uint8_t) (x & 0xff);
40031  len = 2;
40032  } else {
40033  /* Signed integers always map to 4 bytes now. */
40034  buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
40035  buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
40036  buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
40037  buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
40038  buf[4] = (duk_uint8_t) (x & 0xff);
40039  len = 5;
40040  }
40041  duk_debug_write_bytes(thr, buf, len);
40042 }
40043 
40044 /* Write unsigned 32-bit integer. */
40045 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
40046  /* The debugger protocol doesn't support a plain integer encoding for
40047  * the full 32-bit unsigned range (only 32-bit signed). For now,
40048  * unsigned 32-bit values simply written as signed ones. This is not
40049  * a concrete issue except for 32-bit heaphdr fields. Proper solutions
40050  * would be to (a) write such integers as IEEE doubles or (b) add an
40051  * unsigned 32-bit dvalue.
40052  */
40053  if (x >= 0x80000000UL) {
40054  DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
40055  (long) x));
40056  }
40057  duk_debug_write_int(thr, (duk_int32_t) x);
40058 }
40059 
40060 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
40061  duk_uint8_t buf[5];
40062  duk_size_t buflen;
40063 
40064  DUK_ASSERT(thr != NULL);
40065  DUK_ASSERT(length == 0 || data != NULL);
40066 
40067  if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
40068  /* For strings, special form for short lengths. */
40069  buf[0] = (duk_uint8_t) (0x60 + length);
40070  buflen = 1;
40071  } else if (length <= 0xffffUL) {
40072  buf[0] = (duk_uint8_t) (marker_base + 1);
40073  buf[1] = (duk_uint8_t) (length >> 8);
40074  buf[2] = (duk_uint8_t) (length & 0xff);
40075  buflen = 3;
40076  } else {
40077  buf[0] = (duk_uint8_t) marker_base;
40078  buf[1] = (duk_uint8_t) (length >> 24);
40079  buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
40080  buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
40081  buf[4] = (duk_uint8_t) (length & 0xff);
40082  buflen = 5;
40083  }
40084 
40085  duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
40086  duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
40087 }
40088 
40089 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
40090  duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
40091 }
40092 
40093 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
40094  DUK_ASSERT(thr != NULL);
40095 
40096  duk_debug_write_string(thr,
40097  data,
40098  data ? DUK_STRLEN(data) : 0);
40099 }
40100 
40101 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
40102  DUK_ASSERT(thr != NULL);
40103 
40104  /* XXX: differentiate null pointer from empty string? */
40105  duk_debug_write_string(thr,
40106  (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
40107  (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
40108 }
40109 
40110 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
40111  duk_context *ctx = (duk_context *) thr;
40112  duk_debug_write_hstring(thr, duk_safe_to_hstring(ctx, -1));
40113 }
40114 
40115 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
40116  duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
40117 }
40118 
40119 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
40120  DUK_ASSERT(thr != NULL);
40121 
40122  duk_debug_write_buffer(thr,
40123  (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
40124  (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
40125 }
40126 
40127 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
40128  duk_uint8_t buf[2];
40129  duk__ptr_union pu;
40130 
40131  DUK_ASSERT(thr != NULL);
40132  DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
40133  /* ptr may be NULL */
40134 
40135  buf[0] = ibyte;
40136  buf[1] = sizeof(pu);
40137  duk_debug_write_bytes(thr, buf, 2);
40138  pu.p = (void *) ptr;
40139 #if defined(DUK_USE_INTEGER_LE)
40140  duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
40141 #endif
40142  duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
40143 }
40144 
40145 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
40146  duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
40147 }
40148 
40149 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
40150 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
40151  duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
40152 }
40153 #endif /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
40154 
40155 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
40156  duk_uint8_t buf[3];
40157  duk__ptr_union pu;
40158 
40159  DUK_ASSERT(thr != NULL);
40160  DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
40161  DUK_ASSERT(obj != NULL);
40162 
40163  buf[0] = DUK_DBG_IB_OBJECT;
40164  buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
40165  buf[2] = sizeof(pu);
40166  duk_debug_write_bytes(thr, buf, 3);
40167  pu.p = (void *) obj;
40168 #if defined(DUK_USE_INTEGER_LE)
40169  duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
40170 #endif
40171  duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
40172 }
40173 
40174 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
40175  duk_c_function lf_func;
40176  duk_small_uint_t lf_flags;
40177  duk_uint8_t buf[4];
40178  duk_double_union du1;
40179  duk_double_union du2;
40180  duk_int32_t i32;
40181 
40182  DUK_ASSERT(thr != NULL);
40183  DUK_ASSERT(tv != NULL);
40184 
40185  switch (DUK_TVAL_GET_TAG(tv)) {
40186  case DUK_TAG_UNDEFINED:
40187  duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
40188  break;
40189  case DUK_TAG_UNUSED:
40190  duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
40191  break;
40192  case DUK_TAG_NULL:
40193  duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
40194  break;
40195  case DUK_TAG_BOOLEAN:
40196  DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
40197  DUK_TVAL_GET_BOOLEAN(tv) == 1);
40198  duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
40199  break;
40200  case DUK_TAG_POINTER:
40201  duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
40202  break;
40203  case DUK_TAG_LIGHTFUNC:
40204  DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
40205  buf[0] = DUK_DBG_IB_LIGHTFUNC;
40206  buf[1] = (duk_uint8_t) (lf_flags >> 8);
40207  buf[2] = (duk_uint8_t) (lf_flags & 0xff);
40208  buf[3] = sizeof(lf_func);
40209  duk_debug_write_bytes(thr, buf, 4);
40210  duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
40211  break;
40212  case DUK_TAG_STRING:
40213  duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
40214  break;
40215  case DUK_TAG_OBJECT:
40216  duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
40217  break;
40218  case DUK_TAG_BUFFER:
40219  duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
40220  break;
40221 #if defined(DUK_USE_FASTINT)
40222  case DUK_TAG_FASTINT:
40223 #endif
40224  default:
40225  /* Numbers are normalized to big (network) endian. We can
40226  * (but are not required) to use integer dvalues when there's
40227  * no loss of precision.
40228  *
40229  * XXX: share check with other code; this check is slow but
40230  * reliable and doesn't require careful exponent/mantissa
40231  * mask tricks as in the fastint downgrade code.
40232  */
40233  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
40234  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
40235  du1.d = DUK_TVAL_GET_NUMBER(tv);
40236  i32 = (duk_int32_t) du1.d;
40237  du2.d = (duk_double_t) i32;
40238 
40239  DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
40240  "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
40241  (long) i32,
40242  (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
40243  (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
40244  (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
40245  (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
40246  (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
40247  (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
40248  (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
40249  (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
40250 
40251  if (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
40252  duk_debug_write_int(thr, i32);
40253  } else {
40254  DUK_DBLUNION_DOUBLE_HTON(&du1);
40255  duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
40256  duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
40257  }
40258  }
40259 }
40260 
40261 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
40262 /* Variant for writing duk_tvals so that any heap allocated values are
40263  * written out as tagged heap pointers.
40264  */
40265 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
40266  if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
40267  duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
40268  duk_debug_write_heapptr(thr, h);
40269  } else {
40270  duk_debug_write_tval(thr, tv);
40271  }
40272 }
40273 #endif /* DUK_USE_DEBUGGER_DUMPHEAP */
40274 
40275 /*
40276  * Debug connection message write helpers
40277  */
40278 
40279 #if 0 /* unused */
40280 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
40281  duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
40282  duk_debug_write_int(thr, command);
40283 }
40284 #endif
40285 
40286 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
40287  duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
40288 }
40289 
40290 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
40291  /* Allow NULL 'msg' */
40292  duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
40293  duk_debug_write_int(thr, (duk_int32_t) err_code);
40294  duk_debug_write_cstring(thr, msg);
40295  duk_debug_write_eom(thr);
40296 }
40297 
40298 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
40299  duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
40300  duk_debug_write_int(thr, command);
40301 }
40302 
40303 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
40304  duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
40305 
40306  /* As an initial implementation, write flush after every EOM (and the
40307  * version identifier). A better implementation would flush only when
40308  * Duktape is finished processing messages so that a flush only happens
40309  * after all outbound messages are finished on that occasion.
40310  */
40311  duk_debug_write_flush(thr);
40312 }
40313 
40314 /*
40315  * Status message and helpers
40316  */
40317 
40318 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
40319  duk_context *ctx = (duk_context *) thr;
40320  duk_activation *act;
40321  duk_uint_fast32_t line;
40322  duk_uint_fast32_t pc;
40323 
40324  act = duk_hthread_get_current_activation(thr); /* may be NULL */
40325  if (act == NULL) {
40326  return 0;
40327  }
40328 
40329  /* We're conceptually between two opcodes; act->pc indicates the next
40330  * instruction to be executed. This is usually the correct pc/line to
40331  * indicate in Status. (For the 'debugger' statement this now reports
40332  * the pc/line after the debugger statement because the debugger opcode
40333  * has already been executed.)
40334  */
40335 
40336  pc = duk_hthread_get_act_curr_pc(thr, act);
40337 
40338  /* XXX: this should be optimized to be a raw query and avoid valstack
40339  * operations if possible.
40340  */
40341  duk_push_tval(ctx, &act->tv_func);
40342  line = duk_hobject_pc2line_query(ctx, -1, pc);
40343  duk_pop(ctx);
40344  return line;
40345 }
40346 
40347 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
40348  duk_context *ctx = (duk_context *) thr;
40349  duk_activation *act;
40350 
40351  duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
40352  duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
40353 
40354  DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* unsigned */
40355  if (thr->callstack_top == 0) {
40356  duk_debug_write_undefined(thr);
40357  duk_debug_write_undefined(thr);
40358  duk_debug_write_int(thr, 0);
40359  duk_debug_write_int(thr, 0);
40360  } else {
40361  act = thr->callstack + thr->callstack_top - 1;
40362  duk_push_tval(ctx, &act->tv_func);
40363  duk_get_prop_string(ctx, -1, "fileName");
40364  duk__debug_write_hstring_safe_top(thr);
40365  duk_get_prop_string(ctx, -2, "name");
40366  duk__debug_write_hstring_safe_top(thr);
40367  duk_pop_3(ctx);
40368  /* Report next pc/line to be executed. */
40369  duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
40370  duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
40371  }
40372 
40373  duk_debug_write_eom(thr);
40374 }
40375 
40376 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
40377 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
40378  /*
40379  * NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
40380  */
40381 
40382  duk_context *ctx = (duk_context *) thr;
40383  duk_activation *act;
40384  duk_uint32_t pc;
40385 
40386  DUK_ASSERT(thr->valstack_top > thr->valstack); /* At least: ... [err] */
40387 
40388  duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
40389  duk_debug_write_int(thr, fatal);
40390 
40391  /* Report thrown value to client coerced to string */
40392  duk_dup_top(ctx);
40393  duk__debug_write_hstring_safe_top(thr);
40394  duk_pop(ctx);
40395 
40396  if (duk_is_error(ctx, -1)) {
40397  /* Error instance, use augmented error data directly */
40398  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_FILE_NAME);
40399  duk__debug_write_hstring_safe_top(thr);
40400  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_LINE_NUMBER);
40401  duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
40402  } else {
40403  /* For anything other than an Error instance, we calculate the error
40404  * location directly from the current activation.
40405  */
40406  act = thr->callstack + thr->callstack_top - 1;
40407  duk_push_tval(ctx, &act->tv_func);
40408  duk_get_prop_string(ctx, -1, "fileName");
40409  duk__debug_write_hstring_safe_top(thr);
40410  pc = duk_hthread_get_act_prev_pc(thr, act);
40411  duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
40412  }
40413  duk_pop_2(ctx); /* shared pop */
40414 
40415  duk_debug_write_eom(thr);
40416 }
40417 #endif /* DUK_USE_DEBUGGER_THROW_NOTIFY */
40418 
40419 /*
40420  * Debug message processing
40421  */
40422 
40423 /* Skip dvalue. */
40424 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
40425  duk_uint8_t x;
40426  duk_uint32_t len;
40427 
40428  x = duk_debug_read_byte(thr);
40429 
40430  if (x >= 0xc0) {
40431  duk_debug_skip_byte(thr);
40432  return 0;
40433  }
40434  if (x >= 0x80) {
40435  return 0;
40436  }
40437  if (x >= 0x60) {
40438  duk_debug_skip_bytes(thr, x - 0x60);
40439  return 0;
40440  }
40441  switch(x) {
40442  case DUK_DBG_IB_EOM:
40443  return 1; /* Return 1: got EOM */
40444  case DUK_DBG_IB_REQUEST:
40445  case DUK_DBG_IB_REPLY:
40446  case DUK_DBG_IB_ERROR:
40447  case DUK_DBG_IB_NOTIFY:
40448  break;
40449  case DUK_DBG_IB_INT4:
40450  (void) duk__debug_read_uint32_raw(thr);
40451  break;
40452  case DUK_DBG_IB_STR4:
40453  case DUK_DBG_IB_BUF4:
40454  len = duk__debug_read_uint32_raw(thr);
40455  duk_debug_skip_bytes(thr, len);
40456  break;
40457  case DUK_DBG_IB_STR2:
40458  case DUK_DBG_IB_BUF2:
40459  len = duk__debug_read_uint16_raw(thr);
40460  duk_debug_skip_bytes(thr, len);
40461  break;
40462  case DUK_DBG_IB_UNUSED:
40463  case DUK_DBG_IB_UNDEFINED:
40464  case DUK_DBG_IB_NULL:
40465  case DUK_DBG_IB_TRUE:
40466  case DUK_DBG_IB_FALSE:
40467  break;
40468  case DUK_DBG_IB_NUMBER:
40469  duk_debug_skip_bytes(thr, 8);
40470  break;
40471  case DUK_DBG_IB_OBJECT:
40472  duk_debug_skip_byte(thr);
40473  len = duk_debug_read_byte(thr);
40474  duk_debug_skip_bytes(thr, len);
40475  break;
40476  case DUK_DBG_IB_POINTER:
40477  case DUK_DBG_IB_HEAPPTR:
40478  len = duk_debug_read_byte(thr);
40479  duk_debug_skip_bytes(thr, len);
40480  break;
40481  case DUK_DBG_IB_LIGHTFUNC:
40482  duk_debug_skip_bytes(thr, 2);
40483  len = duk_debug_read_byte(thr);
40484  duk_debug_skip_bytes(thr, len);
40485  break;
40486  default:
40487  goto fail;
40488  }
40489 
40490  return 0;
40491 
40492  fail:
40493  DUK__SET_CONN_BROKEN(thr, 1);
40494  return 1; /* Pretend like we got EOM */
40495 }
40496 
40497 /* Skip dvalues to EOM. */
40498 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
40499  for (;;) {
40500  if (duk__debug_skip_dvalue(thr)) {
40501  break;
40502  }
40503  }
40504 }
40505 
40506 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
40507  duk_int32_t level;
40508  level = duk_debug_read_int(thr);
40509  if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
40510  duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
40511  return 0; /* zero indicates failure */
40512  }
40513  return level;
40514 }
40515 
40516 /*
40517  * Simple commands
40518  */
40519 
40520 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
40521  DUK_UNREF(heap);
40522  DUK_D(DUK_DPRINT("debug command Version"));
40523 
40524  duk_debug_write_reply(thr);
40525  duk_debug_write_int(thr, DUK_VERSION);
40526  duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
40527  duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
40528 #if defined(DUK_USE_DOUBLE_LE)
40529  duk_debug_write_int(thr, 1);
40530 #elif defined(DUK_USE_DOUBLE_ME)
40531  duk_debug_write_int(thr, 2);
40532 #elif defined(DUK_USE_DOUBLE_BE)
40533  duk_debug_write_int(thr, 3);
40534 #else
40535  duk_debug_write_int(thr, 0);
40536 #endif
40537  duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
40538  duk_debug_write_eom(thr);
40539 }
40540 
40541 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
40542  DUK_UNREF(heap);
40543  DUK_D(DUK_DPRINT("debug command TriggerStatus"));
40544 
40545  duk_debug_write_reply(thr);
40546  duk_debug_write_eom(thr);
40547  heap->dbg_state_dirty = 1;
40548 }
40549 
40550 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
40551  DUK_D(DUK_DPRINT("debug command Pause"));
40552 
40553  DUK_HEAP_SET_PAUSED(heap);
40554  duk_debug_write_reply(thr);
40555  duk_debug_write_eom(thr);
40556 }
40557 
40558 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
40559  DUK_D(DUK_DPRINT("debug command Resume"));
40560 
40561  DUK_HEAP_CLEAR_PAUSED(heap);
40562  duk_debug_write_reply(thr);
40563  duk_debug_write_eom(thr);
40564 }
40565 
40566 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
40567  duk_small_uint_t step_type;
40568  duk_uint_fast32_t line;
40569 
40570  DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
40571 
40572  if (cmd == DUK_DBG_CMD_STEPINTO) {
40573  step_type = DUK_STEP_TYPE_INTO;
40574  } else if (cmd == DUK_DBG_CMD_STEPOVER) {
40575  step_type = DUK_STEP_TYPE_OVER;
40576  } else {
40577  DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
40578  step_type = DUK_STEP_TYPE_OUT;
40579  }
40580 
40581  line = duk_debug_curr_line(thr);
40582  if (line > 0) {
40583  DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
40584  heap->dbg_step_type = step_type;
40585  heap->dbg_step_thread = thr;
40586  heap->dbg_step_csindex = thr->callstack_top - 1;
40587  heap->dbg_step_startline = line;
40588  heap->dbg_state_dirty = 1;
40589  } else {
40590  DUK_D(DUK_DPRINT("cannot determine current line, stepinto/stepover/stepout ignored"));
40591  }
40592  duk_debug_write_reply(thr);
40593  duk_debug_write_eom(thr);
40594 }
40595 
40596 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
40597  duk_small_int_t i;
40598 
40599  DUK_D(DUK_DPRINT("debug command ListBreak"));
40600  duk_debug_write_reply(thr);
40601  for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
40602  duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
40603  duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
40604  }
40605  duk_debug_write_eom(thr);
40606 }
40607 
40608 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
40609  duk_hstring *filename;
40610  duk_uint32_t linenumber;
40611  duk_small_int_t idx;
40612 
40613  DUK_UNREF(heap);
40614 
40615  filename = duk_debug_read_hstring(thr);
40616  linenumber = (duk_uint32_t) duk_debug_read_int(thr);
40617  DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
40618  idx = duk_debug_add_breakpoint(thr, filename, linenumber);
40619  if (idx >= 0) {
40620  duk_debug_write_reply(thr);
40621  duk_debug_write_int(thr, (duk_int32_t) idx);
40622  duk_debug_write_eom(thr);
40623  } else {
40624  duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
40625  }
40626 }
40627 
40628 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
40629  duk_small_uint_t idx;
40630 
40631  DUK_UNREF(heap);
40632 
40633  DUK_D(DUK_DPRINT("debug command DelBreak"));
40634  idx = (duk_small_uint_t) duk_debug_read_int(thr);
40635  if (duk_debug_remove_breakpoint(thr, idx)) {
40636  duk_debug_write_reply(thr);
40637  duk_debug_write_eom(thr);
40638  } else {
40639  duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
40640  }
40641 }
40642 
40643 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
40644  duk_context *ctx = (duk_context *) thr;
40645  duk_hstring *str;
40646  duk_bool_t rc;
40647  duk_int32_t level;
40648 
40649  DUK_UNREF(heap);
40650  DUK_D(DUK_DPRINT("debug command GetVar"));
40651 
40652  level = duk__debug_read_validate_csindex(thr);
40653  if (level == 0) {
40654  return;
40655  }
40656  str = duk_debug_read_hstring(thr); /* push to stack */
40657  DUK_ASSERT(str != NULL);
40658 
40659  if (thr->callstack_top > 0) {
40660  rc = duk_js_getvar_activation(thr,
40661  thr->callstack + thr->callstack_top + level,
40662  str,
40663  0);
40664  } else {
40665  /* No activation, no variable access. Could also pretend
40666  * we're in the global program context and read stuff off
40667  * the global object.
40668  */
40669  DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore getvar"));
40670  rc = 0;
40671  }
40672 
40673  duk_debug_write_reply(thr);
40674  if (rc) {
40675  duk_debug_write_int(thr, 1);
40676  DUK_ASSERT(duk_get_tval(ctx, -2) != NULL);
40677  duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
40678  } else {
40679  duk_debug_write_int(thr, 0);
40680  duk_debug_write_unused(thr);
40681  }
40682  duk_debug_write_eom(thr);
40683 }
40684 
40685 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
40686  duk_hstring *str;
40687  duk_tval *tv;
40688  duk_int32_t level;
40689 
40690  DUK_UNREF(heap);
40691  DUK_D(DUK_DPRINT("debug command PutVar"));
40692 
40693  level = duk__debug_read_validate_csindex(thr);
40694  if (level == 0) {
40695  return;
40696  }
40697  str = duk_debug_read_hstring(thr); /* push to stack */
40698  DUK_ASSERT(str != NULL);
40699  tv = duk_debug_read_tval(thr);
40700  if (tv == NULL) {
40701  /* detached */
40702  return;
40703  }
40704 
40705  if (thr->callstack_top > 0) {
40706  duk_js_putvar_activation(thr,
40707  thr->callstack + thr->callstack_top + level,
40708  str,
40709  tv,
40710  0);
40711  } else {
40712  DUK_D(DUK_DPRINT("callstack empty, no activation -> ignore putvar"));
40713  }
40714 
40715  /* XXX: Current putvar implementation doesn't have a success flag,
40716  * add one and send to debug client?
40717  */
40718  duk_debug_write_reply(thr);
40719  duk_debug_write_eom(thr);
40720 }
40721 
40722 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
40723  duk_context *ctx = (duk_context *) thr;
40724  duk_hthread *curr_thr = thr;
40725  duk_activation *curr_act;
40726  duk_uint_fast32_t pc;
40727  duk_uint_fast32_t line;
40728  duk_size_t i;
40729 
40730  DUK_ASSERT(thr != NULL);
40731  DUK_UNREF(heap);
40732 
40733  duk_debug_write_reply(thr);
40734  while (curr_thr != NULL) {
40735  i = curr_thr->callstack_top;
40736  while (i > 0) {
40737  i--;
40738  curr_act = curr_thr->callstack + i;
40739 
40740  /* PC/line semantics here are:
40741  * - For callstack top we're conceptually between two
40742  * opcodes and current PC indicates next line to
40743  * execute, so report that (matches Status).
40744  * - For other activations we're conceptually still
40745  * executing the instruction at PC-1, so report that
40746  * (matches error stacktrace behavior).
40747  * - See: https://github.com/svaarala/duktape/issues/281
40748  */
40749 
40750  /* XXX: optimize to use direct reads, i.e. avoid
40751  * value stack operations.
40752  */
40753  duk_push_tval(ctx, &curr_act->tv_func);
40754  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_FILE_NAME);
40755  duk__debug_write_hstring_safe_top(thr);
40756  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME);
40757  duk__debug_write_hstring_safe_top(thr);
40758  pc = duk_hthread_get_act_curr_pc(thr, curr_act);
40759  if (i != curr_thr->callstack_top - 1 && pc > 0) {
40760  pc--;
40761  }
40762  line = duk_hobject_pc2line_query(ctx, -3, pc);
40763  duk_debug_write_uint(thr, (duk_uint32_t) line);
40764  duk_debug_write_uint(thr, (duk_uint32_t) pc);
40765  duk_pop_3(ctx);
40766  }
40767  curr_thr = curr_thr->resumer;
40768  }
40769  /* SCANBUILD: warning about 'thr' potentially being NULL here,
40770  * warning is incorrect because thr != NULL always here.
40771  */
40772  duk_debug_write_eom(thr);
40773 }
40774 
40775 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
40776  duk_context *ctx = (duk_context *) thr;
40777  duk_activation *curr_act;
40778  duk_int32_t level;
40779  duk_hstring *varname;
40780 
40781  DUK_UNREF(heap);
40782 
40783  level = duk__debug_read_validate_csindex(thr);
40784  if (level == 0) {
40785  return;
40786  }
40787  duk_debug_write_reply(thr);
40788 
40789  curr_act = thr->callstack + thr->callstack_top + level;
40790 
40791  /* XXX: several nice-to-have improvements here:
40792  * - Use direct reads avoiding value stack operations
40793  * - Avoid triggering getters, indicate getter values to debug client
40794  * - If side effects are possible, add error catching
40795  */
40796 
40797  duk_push_tval(ctx, &curr_act->tv_func);
40798  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VARMAP);
40799  if (duk_is_object(ctx, -1)) {
40800  duk_enum(ctx, -1, 0 /*enum_flags*/);
40801  while (duk_next(ctx, -1 /*enum_index*/, 0 /*get_value*/)) {
40802  varname = duk_known_hstring(ctx, -1);
40803 
40804  duk_js_getvar_activation(thr, curr_act, varname, 0 /*throw_flag*/);
40805  /* [ ... func varmap enum key value this ] */
40806  duk_debug_write_hstring(thr, duk_get_hstring(ctx, -3));
40807  duk_debug_write_tval(thr, duk_get_tval(ctx, -2));
40808  duk_pop_3(ctx); /* -> [ ... func varmap enum ] */
40809  }
40810  } else {
40811  DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
40812  }
40813 
40814  duk_debug_write_eom(thr);
40815 }
40816 
40817 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
40818  duk_context *ctx = (duk_context *) thr;
40819  duk_small_uint_t call_flags;
40820  duk_int_t call_ret;
40821  duk_small_int_t eval_err;
40822  duk_int_t num_eval_args;
40823  duk_bool_t direct_eval;
40824  duk_int32_t level;
40825 
40826  DUK_UNREF(heap);
40827 
40828  DUK_D(DUK_DPRINT("debug command Eval"));
40829 
40830  /* The eval code is executed within the lexical environment of a specified
40831  * activation. For now, use global object eval() function, with the eval
40832  * considered a 'direct call to eval'.
40833  *
40834  * Callstack index for debug commands only affects scope -- the callstack
40835  * as seen by, e.g. Duktape.act() will be the same regardless.
40836  */
40837 
40838  /* nargs == 2 so we can pass a callstack index to eval(). */
40839  duk_push_c_function(ctx, duk_bi_global_object_eval, 2 /*nargs*/);
40840  duk_push_undefined(ctx); /* 'this' binding shouldn't matter here */
40841 
40842  /* Read callstack index, if non-null. */
40843  if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
40844  direct_eval = 0;
40845  (void) duk_debug_read_byte(thr);
40846  } else {
40847  direct_eval = 1;
40848  level = duk__debug_read_validate_csindex(thr);
40849  if (level == 0) {
40850  return;
40851  }
40852  }
40853 
40854  DUK_ASSERT(!direct_eval ||
40855  (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
40856 
40857  (void) duk_debug_read_hstring(thr);
40858  if (direct_eval) {
40859  num_eval_args = 2;
40860  duk_push_int(ctx, level - 1); /* compensate for eval() call */
40861  } else {
40862  num_eval_args = 1;
40863  }
40864 
40865  /* [ ... eval "eval" eval_input level ] */
40866 
40867  call_flags = 0;
40868  if (direct_eval && thr->callstack_top >= (duk_size_t) -level) {
40869  duk_activation *act;
40870  duk_hobject *fun;
40871 
40872  act = thr->callstack + thr->callstack_top + level;
40873  fun = DUK_ACT_GET_FUNC(act);
40874  if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
40875  /* Direct eval requires that there's a current
40876  * activation and it is an Ecmascript function.
40877  * When Eval is executed from e.g. cooperate API
40878  * call we'll need to do an indirect eval instead.
40879  */
40880  call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
40881  }
40882  }
40883 
40884  call_ret = duk_handle_call_protected(thr, num_eval_args, call_flags);
40885 
40886  if (call_ret == DUK_EXEC_SUCCESS) {
40887  eval_err = 0;
40888  /* Use result value as is. */
40889  } else {
40890  /* For errors a string coerced result is most informative
40891  * right now, as the debug client doesn't have the capability
40892  * to traverse the error object.
40893  */
40894  eval_err = 1;
40895  duk_safe_to_string(ctx, -1);
40896  }
40897 
40898  /* [ ... result ] */
40899 
40900  duk_debug_write_reply(thr);
40901  duk_debug_write_int(thr, (duk_int32_t) eval_err);
40902  DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
40903  duk_debug_write_tval(thr, duk_get_tval(ctx, -1));
40904  duk_debug_write_eom(thr);
40905 }
40906 
40907 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
40908  DUK_UNREF(heap);
40909  DUK_D(DUK_DPRINT("debug command Detach"));
40910 
40911  duk_debug_write_reply(thr);
40912  duk_debug_write_eom(thr);
40913 
40914  DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
40915  DUK__SET_CONN_BROKEN(thr, 0); /* not an error */
40916 }
40917 
40918 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
40919  duk_context *ctx = (duk_context *) thr;
40920  duk_idx_t old_top;
40921 
40922  DUK_D(DUK_DPRINT("debug command AppRequest"));
40923 
40924  old_top = duk_get_top(ctx); /* save stack top */
40925 
40926  if (heap->dbg_request_cb != NULL) {
40927  duk_idx_t nrets;
40928  duk_idx_t nvalues = 0;
40929  duk_idx_t top, idx;
40930 
40931  /* Read tvals from the message and push them onto the valstack,
40932  * then call the request callback to process the request.
40933  */
40934  while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
40935  duk_tval *tv;
40936  if (!duk_check_stack(ctx, 1)) {
40937  DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
40938  goto fail;
40939  }
40940  tv = duk_debug_read_tval(thr); /* push to stack */
40941  if (tv == NULL) {
40942  /* detached */
40943  return;
40944  }
40945  nvalues++;
40946  }
40947  DUK_ASSERT(duk_get_top(ctx) == old_top + nvalues);
40948 
40949  /* Request callback should push values for reply to client onto valstack */
40950  DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
40951  (long) nvalues, (long) old_top, (long) duk_get_top(ctx)));
40952  nrets = heap->dbg_request_cb(ctx, heap->dbg_udata, nvalues);
40953  DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
40954  (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(ctx)));
40955  if (nrets >= 0) {
40956  DUK_ASSERT(duk_get_top(ctx) >= old_top + nrets);
40957  if (duk_get_top(ctx) < old_top + nrets) {
40958  DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
40959  "top=%ld < old_top=%ld + nrets=%ld; "
40960  "this might mean it's unsafe to continue!",
40961  (long) duk_get_top(ctx), (long) old_top, (long) nrets));
40962  goto fail;
40963  }
40964 
40965  /* Reply with tvals pushed by request callback */
40966  duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
40967  top = duk_get_top(ctx);
40968  for (idx = top - nrets; idx < top; idx++) {
40969  duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(ctx, idx));
40970  }
40971  duk_debug_write_eom(thr);
40972  } else {
40973  DUK_ASSERT(duk_get_top(ctx) >= old_top + 1);
40974  if (duk_get_top(ctx) < old_top + 1) {
40975  DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
40976  goto fail;
40977  }
40978  duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(ctx, -1));
40979  }
40980 
40981  duk_set_top(ctx, old_top); /* restore stack top */
40982  } else {
40983  DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
40984  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
40985  }
40986 
40987  return;
40988 
40989  fail:
40990  duk_set_top(ctx, old_top); /* restore stack top */
40991  DUK__SET_CONN_BROKEN(thr, 1);
40992 }
40993 
40994 /*
40995  * DumpHeap command
40996  */
40997 
40998 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
40999 /* XXX: this has some overlap with object inspection; remove this and make
41000  * DumpHeap return lists of heapptrs instead?
41001  */
41002 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
41003  DUK_UNREF(heap);
41004 
41005  duk_debug_write_heapptr(thr, hdr);
41006  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
41007  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
41008 #if defined(DUK_USE_REFERENCE_COUNTING)
41009  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
41010 #else
41011  duk_debug_write_int(thr, (duk_int32_t) -1);
41012 #endif
41013 
41014  switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
41015  case DUK_HTYPE_STRING: {
41016  duk_hstring *h = (duk_hstring *) hdr;
41017 
41018  duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_BYTELEN(h));
41019  duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_CHARLEN(h));
41020  duk_debug_write_uint(thr, (duk_int32_t) DUK_HSTRING_GET_HASH(h));
41021  duk_debug_write_hstring(thr, h);
41022  break;
41023  }
41024  case DUK_HTYPE_OBJECT: {
41025  duk_hobject *h = (duk_hobject *) hdr;
41026  duk_hstring *k;
41027  duk_uint_fast32_t i;
41028 
41029  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
41030  duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
41031  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
41032  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
41033  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
41034  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
41035 
41036  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
41037  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
41038  k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
41039  duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
41040  if (k == NULL) {
41041  duk_debug_write_int(thr, 0); /* isAccessor */
41042  duk_debug_write_unused(thr);
41043  continue;
41044  }
41045  if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
41046  duk_debug_write_int(thr, 1); /* isAccessor */
41047  duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
41048  duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
41049  } else {
41050  duk_debug_write_int(thr, 0); /* isAccessor */
41051 
41052  duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
41053  }
41054  }
41055 
41056  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
41057  /* Note: array dump will include elements beyond
41058  * 'length'.
41059  */
41060  duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
41061  }
41062  break;
41063  }
41064  case DUK_HTYPE_BUFFER: {
41065  duk_hbuffer *h = (duk_hbuffer *) hdr;
41066 
41067  duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
41068  duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
41069  break;
41070  }
41071  default: {
41072  DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
41073  }
41074  }
41075 }
41076 
41077 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
41078  duk_heaphdr *hdr;
41079 
41080  hdr = heap->heap_allocated;
41081  while (hdr != NULL) {
41082  duk__debug_dump_heaphdr(thr, heap, hdr);
41083  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
41084  }
41085 }
41086 
41087 #if defined(DUK_USE_STRTAB_CHAIN)
41088 DUK_LOCAL void duk__debug_dump_strtab_chain(duk_hthread *thr, duk_heap *heap) {
41089  duk_uint_fast32_t i, j;
41090  duk_strtab_entry *e;
41091 #if defined(DUK_USE_HEAPPTR16)
41092  duk_uint16_t *lst;
41093 #else
41094  duk_hstring **lst;
41095 #endif
41096  duk_hstring *h;
41097 
41098  for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
41099  e = heap->strtable + i;
41100  if (e->listlen > 0) {
41101 #if defined(DUK_USE_HEAPPTR16)
41102  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
41103 #else
41104  lst = e->u.strlist;
41105 #endif
41106  DUK_ASSERT(lst != NULL);
41107 
41108  for (j = 0; j < e->listlen; j++) {
41109 #if defined(DUK_USE_HEAPPTR16)
41110  h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
41111 #else
41112  h = lst[j];
41113 #endif
41114  if (h != NULL) {
41115  duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
41116  }
41117  }
41118  } else {
41119 #if defined(DUK_USE_HEAPPTR16)
41120  h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
41121 #else
41122  h = e->u.str;
41123 #endif
41124  if (h != NULL) {
41125  duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
41126  }
41127  }
41128  }
41129 }
41130 #endif /* DUK_USE_STRTAB_CHAIN */
41131 
41132 #if defined(DUK_USE_STRTAB_PROBE)
41133 DUK_LOCAL void duk__debug_dump_strtab_probe(duk_hthread *thr, duk_heap *heap) {
41134  duk_uint32_t i;
41135  duk_hstring *h;
41136 
41137  for (i = 0; i < heap->st_size; i++) {
41138 #if defined(DUK_USE_HEAPPTR16)
41139  h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
41140 #else
41141  h = heap->strtable[i];
41142 #endif
41143  if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
41144  continue;
41145  }
41146 
41147  duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
41148  }
41149 }
41150 #endif /* DUK_USE_STRTAB_PROBE */
41151 
41152 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
41153  DUK_D(DUK_DPRINT("debug command DumpHeap"));
41154 
41155  duk_debug_write_reply(thr);
41156  duk__debug_dump_heap_allocated(thr, heap);
41157 #if defined(DUK_USE_STRTAB_CHAIN)
41158  duk__debug_dump_strtab_chain(thr, heap);
41159 #endif
41160 #if defined(DUK_USE_STRTAB_PROBE)
41161  duk__debug_dump_strtab_probe(thr, heap);
41162 #endif
41163  duk_debug_write_eom(thr);
41164 }
41165 #endif /* DUK_USE_DEBUGGER_DUMPHEAP */
41166 
41167 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
41168  duk_activation *act;
41169  duk_hcompfunc *fun = NULL;
41170  duk_size_t i, n;
41171  duk_tval *tv;
41172  duk_hobject **fn;
41173  duk_int32_t level = -1;
41174  duk_uint8_t ibyte;
41175 
41176  DUK_UNREF(heap);
41177 
41178  DUK_D(DUK_DPRINT("debug command GetBytecode"));
41179 
41180  ibyte = duk_debug_peek_byte(thr);
41181  if (ibyte != DUK_DBG_IB_EOM) {
41182  tv = duk_debug_read_tval(thr);
41183  if (tv == NULL) {
41184  /* detached */
41185  return;
41186  }
41187  if (DUK_TVAL_IS_OBJECT(tv)) {
41188  /* tentative, checked later */
41189  fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
41190  DUK_ASSERT(fun != NULL);
41191  } else if (DUK_TVAL_IS_NUMBER(tv)) {
41192  level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
41193  } else {
41194  DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
41195  goto fail_args;
41196  }
41197  }
41198 
41199  if (fun == NULL) {
41200  if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
41201  DUK_D(DUK_DPRINT("invalid callstack index for GetBytecode"));
41202  goto fail_index;
41203  }
41204  act = thr->callstack + thr->callstack_top + level;
41205  fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
41206  }
41207 
41208  if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
41209  DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
41210  goto fail_args;
41211  }
41212  DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
41213 
41214  duk_debug_write_reply(thr);
41215  n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
41216  duk_debug_write_int(thr, (duk_int32_t) n);
41217  tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
41218  for (i = 0; i < n; i++) {
41219  duk_debug_write_tval(thr, tv);
41220  tv++;
41221  }
41222  n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
41223  duk_debug_write_int(thr, (duk_int32_t) n);
41224  fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
41225  for (i = 0; i < n; i++) {
41226  duk_debug_write_hobject(thr, *fn);
41227  fn++;
41228  }
41229  duk_debug_write_string(thr,
41230  (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
41231  (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
41232  duk_debug_write_eom(thr);
41233  return;
41234 
41235  fail_args:
41236  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
41237  return;
41238 
41239  fail_index:
41240  duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
41241  return;
41242 }
41243 
41244 /*
41245  * Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
41246  * GetObjPropDescRange
41247  */
41248 
41249 #if defined(DUK_USE_DEBUGGER_INSPECT)
41250 
41251 #if 0 /* pruned */
41252 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
41253  "reachable",
41254  "temproot",
41255  "finalizable",
41256  "finalized",
41257  "readonly"
41258  /* NULL not needed here */
41259 };
41260 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
41261  DUK_HEAPHDR_FLAG_REACHABLE,
41262  DUK_HEAPHDR_FLAG_TEMPROOT,
41263  DUK_HEAPHDR_FLAG_FINALIZABLE,
41264  DUK_HEAPHDR_FLAG_FINALIZED,
41265  DUK_HEAPHDR_FLAG_READONLY,
41266  0 /* terminator */
41267 };
41268 #endif
41269 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
41270 #if 0
41271  "arridx",
41272  "symbol",
41273  "hidden",
41274  "reserved_word",
41275  "strict_reserved_word",
41276  "eval_or_arguments",
41277 #endif
41278  "extdata"
41279  /* NULL not needed here */
41280 };
41281 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
41282 #if 0
41283  DUK_HSTRING_FLAG_ARRIDX,
41284  DUK_HSTRING_FLAG_SYMBOL,
41285  DUK_HSTRING_FLAG_HIDDEN,
41286  DUK_HSTRING_FLAG_RESERVED_WORD,
41287  DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
41288  DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
41289 #endif
41290  DUK_HSTRING_FLAG_EXTDATA,
41291  0 /* terminator */
41292 };
41293 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
41294  "extensible",
41295  "constructable",
41296  "boundfunc",
41297  "compfunc",
41298  "natfunc",
41299  "bufobj",
41300  "thread",
41301  "array_part",
41302  "strict",
41303  "notail",
41304  "newenv",
41305  "namebinding",
41306  "createargs",
41307  "envrecclosed",
41308  "exotic_array",
41309  "exotic_stringobj",
41310  "exotic_arguments",
41311  "exotic_dukfunc",
41312  "exotic_proxyobj"
41313  /* NULL not needed here */
41314 };
41315 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
41316  DUK_HOBJECT_FLAG_EXTENSIBLE,
41317  DUK_HOBJECT_FLAG_CONSTRUCTABLE,
41318  DUK_HOBJECT_FLAG_BOUNDFUNC,
41319  DUK_HOBJECT_FLAG_COMPFUNC,
41320  DUK_HOBJECT_FLAG_NATFUNC,
41321  DUK_HOBJECT_FLAG_BUFOBJ,
41322  DUK_HOBJECT_FLAG_THREAD,
41323  DUK_HOBJECT_FLAG_ARRAY_PART,
41324  DUK_HOBJECT_FLAG_STRICT,
41325  DUK_HOBJECT_FLAG_NOTAIL,
41326  DUK_HOBJECT_FLAG_NEWENV,
41327  DUK_HOBJECT_FLAG_NAMEBINDING,
41328  DUK_HOBJECT_FLAG_CREATEARGS,
41329  DUK_HOBJECT_FLAG_ENVRECCLOSED,
41330  DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
41331  DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
41332  DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
41333  DUK_HOBJECT_FLAG_EXOTIC_DUKFUNC,
41334  DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
41335  0 /* terminator */
41336 };
41337 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
41338  "dynamic",
41339  "external"
41340  /* NULL not needed here */
41341 };
41342 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
41343  DUK_HBUFFER_FLAG_DYNAMIC,
41344  DUK_HBUFFER_FLAG_EXTERNAL,
41345  0 /* terminator */
41346 };
41347 
41348 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
41349  duk_debug_write_uint(thr, 0);
41350  duk_debug_write_cstring(thr, key);
41351 }
41352 
41353 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
41354  duk_debug_write_uint(thr, 0);
41355  duk_debug_write_cstring(thr, key);
41356  duk_debug_write_uint(thr, val);
41357 }
41358 
41359 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
41360  duk_debug_write_uint(thr, 0);
41361  duk_debug_write_cstring(thr, key);
41362  duk_debug_write_int(thr, val);
41363 }
41364 
41365 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
41366  duk_debug_write_uint(thr, 0);
41367  duk_debug_write_cstring(thr, key);
41368  duk_debug_write_boolean(thr, val);
41369 }
41370 
41371 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
41372  const char *key;
41373  duk_uint_t mask;
41374 
41375  for (;;) {
41376  mask = *masks++;
41377  if (!mask) {
41378  break;
41379  }
41380  key = *keys++;
41381  DUK_ASSERT(key != NULL);
41382 
41383  DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
41384  duk__debug_getinfo_prop_bool(thr, key, flags & mask);
41385  }
41386 }
41387 
41388 /* Inspect a property using a virtual index into a conceptual property list
41389  * consisting of (1) all array part items from [0,a_size[ (even when above
41390  * .length) and (2) all entry part items from [0,e_next[. Unused slots are
41391  * indicated using dvalue 'unused'.
41392  */
41393 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
41394  duk_uint_t a_size;
41395  duk_tval *tv;
41396  duk_hstring *h_key;
41397  duk_hobject *h_getset;
41398  duk_uint_t flags;
41399 
41400  DUK_UNREF(heap);
41401 
41402  a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
41403  if (idx < a_size) {
41404  duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
41405  duk_debug_write_uint(thr, idx);
41406  tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
41407  duk_debug_write_tval(thr, tv);
41408  return 1;
41409  }
41410 
41411  idx -= a_size;
41412  if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
41413  return 0;
41414  }
41415 
41416  h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
41417  if (h_key == NULL) {
41418  duk_debug_write_uint(thr, 0);
41419  duk_debug_write_null(thr);
41420  duk_debug_write_unused(thr);
41421  return 1;
41422  }
41423 
41424  flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
41425  if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
41426  flags |= DUK_DBG_PROPFLAG_SYMBOL;
41427  }
41428  if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
41429  flags |= DUK_DBG_PROPFLAG_HIDDEN;
41430  }
41431  duk_debug_write_uint(thr, flags);
41432  duk_debug_write_hstring(thr, h_key);
41433  if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
41434  h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
41435  if (h_getset) {
41436  duk_debug_write_hobject(thr, h_getset);
41437  } else {
41438  duk_debug_write_null(thr);
41439  }
41440  h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
41441  if (h_getset) {
41442  duk_debug_write_hobject(thr, h_getset);
41443  } else {
41444  duk_debug_write_null(thr);
41445  }
41446  } else {
41447  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
41448  duk_debug_write_tval(thr, tv);
41449  }
41450  return 1;
41451 }
41452 
41453 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
41454  duk_heaphdr *h;
41455 
41456  DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
41457  DUK_UNREF(heap);
41458 
41459  h = duk_debug_read_any_ptr(thr);
41460  if (!h) {
41461  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
41462  return;
41463  }
41464 
41465  duk_debug_write_reply(thr);
41466 
41467  /* As with all inspection code, we rely on the debug client providing
41468  * a valid, non-stale pointer: there's no portable way to safely
41469  * validate the pointer here.
41470  */
41471 
41472  duk__debug_getinfo_flags_key(thr, "heapptr");
41473  duk_debug_write_heapptr(thr, h);
41474 
41475  /* XXX: comes out as signed now */
41476  duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
41477  duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
41478 #if defined(DUK_USE_REFERENCE_COUNTING)
41479  duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
41480 #endif
41481 #if 0 /* pruned */
41482  duk__debug_getinfo_bitmask(thr,
41483  duk__debug_getinfo_heaphdr_keys,
41484  duk__debug_getinfo_heaphdr_masks,
41485  DUK_HEAPHDR_GET_FLAGS_RAW(h));
41486 #endif
41487 
41488  switch (DUK_HEAPHDR_GET_TYPE(h)) {
41489  case DUK_HTYPE_STRING: {
41490  duk_hstring *h_str;
41491 
41492  h_str = (duk_hstring *) h;
41493  duk__debug_getinfo_bitmask(thr,
41494  duk__debug_getinfo_hstring_keys,
41495  duk__debug_getinfo_hstring_masks,
41496  DUK_HEAPHDR_GET_FLAGS_RAW(h));
41497  duk__debug_getinfo_prop_uint(thr, "bytelen", DUK_HSTRING_GET_BYTELEN(h_str));
41498  duk__debug_getinfo_prop_uint(thr, "charlen", DUK_HSTRING_GET_CHARLEN(h_str));
41499  duk__debug_getinfo_prop_uint(thr, "hash", DUK_HSTRING_GET_HASH(h_str));
41500  duk__debug_getinfo_flags_key(thr, "data");
41501  duk_debug_write_hstring(thr, h_str);
41502  break;
41503  }
41504  case DUK_HTYPE_OBJECT: {
41505  duk_hobject *h_obj;
41506  duk_hobject *h_proto;
41507 
41508  h_obj = (duk_hobject *) h;
41509  h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
41510 
41511  /* duk_hobject specific fields. */
41512  duk__debug_getinfo_bitmask(thr,
41513  duk__debug_getinfo_hobject_keys,
41514  duk__debug_getinfo_hobject_masks,
41515  DUK_HEAPHDR_GET_FLAGS_RAW(h));
41516  duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
41517  duk__debug_getinfo_flags_key(thr, "class_name");
41518  duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
41519  duk__debug_getinfo_flags_key(thr, "prototype");
41520  if (h_proto != NULL) {
41521  duk_debug_write_hobject(thr, h_proto);
41522  } else {
41523  duk_debug_write_null(thr);
41524  }
41525  duk__debug_getinfo_flags_key(thr, "props");
41526  duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
41527  duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
41528  duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
41529  duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
41530  duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
41531 
41532  if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
41533  duk_harray *h_arr;
41534  h_arr = (duk_harray *) h_obj;
41535 
41536  duk__debug_getinfo_prop_int(thr, "length", h_arr->length);
41537  duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
41538  }
41539 
41540  if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
41541  duk_hnatfunc *h_fun;
41542  h_fun = (duk_hnatfunc *) h_obj;
41543 
41544  duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
41545  duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
41546  duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
41547  /* Native function pointer may be different from a void pointer,
41548  * and we serialize it from memory directly now (no byte swapping etc).
41549  */
41550  duk__debug_getinfo_flags_key(thr, "funcptr");
41551  duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
41552  }
41553 
41554  if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
41555  duk_hcompfunc *h_fun;
41556  duk_hbuffer *h_buf;
41557  duk_hobject *h_lexenv;
41558  duk_hobject *h_varenv;
41559  h_fun = (duk_hcompfunc *) h_obj;
41560 
41561  duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
41562  duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
41563 
41564  duk__debug_getinfo_flags_key(thr, "lex_env");
41565  h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
41566  if (h_lexenv != NULL) {
41567  duk_debug_write_hobject(thr, h_lexenv);
41568  } else {
41569  duk_debug_write_null(thr);
41570  }
41571  duk__debug_getinfo_flags_key(thr, "var_env");
41572  h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
41573  if (h_varenv != NULL) {
41574  duk_debug_write_hobject(thr, h_varenv);
41575  } else {
41576  duk_debug_write_null(thr);
41577  }
41578 
41579  duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
41580  duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
41581  h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
41582  if (h_buf != NULL) {
41583  duk__debug_getinfo_flags_key(thr, "data");
41584  duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
41585  }
41586  }
41587 
41588  if (DUK_HOBJECT_IS_THREAD(h_obj)) {
41589  /* XXX: Currently no inspection of threads, e.g. value stack, call
41590  * stack, catch stack, etc.
41591  */
41592  duk_hthread *h_thr;
41593  h_thr = (duk_hthread *) h_obj;
41594  DUK_UNREF(h_thr);
41595  }
41596 
41597 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
41598  if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
41599  duk_hbufobj *h_bufobj;
41600  h_bufobj = (duk_hbufobj *) h_obj;
41601 
41602  duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
41603  duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
41604  duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
41605  duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
41606  duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
41607  if (h_bufobj->buf != NULL) {
41608  duk__debug_getinfo_flags_key(thr, "buffer");
41609  duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
41610  }
41611  }
41612 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
41613  break;
41614  }
41615  case DUK_HTYPE_BUFFER: {
41616  duk_hbuffer *h_buf;
41617 
41618  h_buf = (duk_hbuffer *) h;
41619  duk__debug_getinfo_bitmask(thr,
41620  duk__debug_getinfo_hbuffer_keys,
41621  duk__debug_getinfo_hbuffer_masks,
41622  DUK_HEAPHDR_GET_FLAGS_RAW(h));
41623  duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
41624  duk__debug_getinfo_flags_key(thr, "dataptr");
41625  duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
41626  duk__debug_getinfo_flags_key(thr, "data");
41627  duk_debug_write_hbuffer(thr, h_buf); /* tolerates NULL h_buf */
41628  break;
41629  }
41630  default: {
41631  /* Since we already started writing the reply, just emit nothing. */
41632  DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
41633  }
41634  }
41635 
41636  duk_debug_write_eom(thr);
41637 }
41638 
41639 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
41640  duk_heaphdr *h;
41641  duk_hobject *h_obj;
41642  duk_hstring *h_key;
41643  duk_propdesc desc;
41644 
41645  DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
41646  DUK_UNREF(heap);
41647 
41648  h = duk_debug_read_any_ptr(thr);
41649  if (!h) {
41650  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
41651  return;
41652  }
41653  h_key = duk_debug_read_hstring(thr);
41654  if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
41655  goto fail_args;
41656  }
41657  h_obj = (duk_hobject *) h;
41658 
41659  if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
41660  duk_int_t virtual_idx;
41661  duk_bool_t rc;
41662 
41663  /* To use the shared helper need the virtual index. */
41664  DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
41665  virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
41666  (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
41667 
41668  duk_debug_write_reply(thr);
41669  rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
41670  DUK_ASSERT(rc == 1);
41671  DUK_UNREF(rc);
41672  duk_debug_write_eom(thr);
41673  } else {
41674  duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
41675  }
41676  return;
41677 
41678  fail_args:
41679  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
41680 }
41681 
41682 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
41683  duk_heaphdr *h;
41684  duk_hobject *h_obj;
41685  duk_uint_t idx, idx_start, idx_end;
41686 
41687  DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
41688  DUK_UNREF(heap);
41689 
41690  h = duk_debug_read_any_ptr(thr);
41691  idx_start = duk_debug_read_int(thr);
41692  idx_end = duk_debug_read_int(thr);
41693  if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
41694  goto fail_args;
41695  }
41696  h_obj = (duk_hobject *) h;
41697 
41698  /* The index range space is conceptually the array part followed by the
41699  * entry part. Unlike normal enumeration all slots are exposed here as
41700  * is and return 'unused' if the slots are not in active use. In particular
41701  * the array part is included for the full a_size regardless of what the
41702  * array .length is.
41703  */
41704 
41705  duk_debug_write_reply(thr);
41706  for (idx = idx_start; idx < idx_end; idx++) {
41707  if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
41708  break;
41709  }
41710  }
41711  duk_debug_write_eom(thr);
41712  return;
41713 
41714  fail_args:
41715  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
41716 }
41717 
41718 #endif /* DUK_USE_DEBUGGER_INSPECT */
41719 
41720 /*
41721  * Process incoming debug requests
41722  *
41723  * Individual request handlers can push temporaries on the value stack and
41724  * rely on duk__debug_process_message() to restore the value stack top
41725  * automatically.
41726  */
41727 
41728 /* Process one debug message. Automatically restore value stack top to its
41729  * entry value, so that individual message handlers don't need exact value
41730  * stack handling which is convenient.
41731  */
41732 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
41733  duk_context *ctx = (duk_context *) thr;
41734  duk_heap *heap;
41735  duk_uint8_t x;
41736  duk_int32_t cmd;
41737  duk_idx_t entry_top;
41738 
41739  DUK_ASSERT(thr != NULL);
41740  heap = thr->heap;
41741  DUK_ASSERT(heap != NULL);
41742  DUK_UNREF(ctx);
41743 
41744  entry_top = duk_get_top(ctx);
41745 
41746  x = duk_debug_read_byte(thr);
41747  switch (x) {
41748  case DUK_DBG_IB_REQUEST: {
41749  cmd = duk_debug_read_int(thr);
41750  switch (cmd) {
41751  case DUK_DBG_CMD_BASICINFO: {
41752  duk__debug_handle_basic_info(thr, heap);
41753  break;
41754  }
41755  case DUK_DBG_CMD_TRIGGERSTATUS: {
41756  duk__debug_handle_trigger_status(thr, heap);
41757  break;
41758  }
41759  case DUK_DBG_CMD_PAUSE: {
41760  duk__debug_handle_pause(thr, heap);
41761  break;
41762  }
41763  case DUK_DBG_CMD_RESUME: {
41764  duk__debug_handle_resume(thr, heap);
41765  break;
41766  }
41767  case DUK_DBG_CMD_STEPINTO:
41768  case DUK_DBG_CMD_STEPOVER:
41769  case DUK_DBG_CMD_STEPOUT: {
41770  duk__debug_handle_step(thr, heap, cmd);
41771  break;
41772  }
41773  case DUK_DBG_CMD_LISTBREAK: {
41774  duk__debug_handle_list_break(thr, heap);
41775  break;
41776  }
41777  case DUK_DBG_CMD_ADDBREAK: {
41778  duk__debug_handle_add_break(thr, heap);
41779  break;
41780  }
41781  case DUK_DBG_CMD_DELBREAK: {
41782  duk__debug_handle_del_break(thr, heap);
41783  break;
41784  }
41785  case DUK_DBG_CMD_GETVAR: {
41786  duk__debug_handle_get_var(thr, heap);
41787  break;
41788  }
41789  case DUK_DBG_CMD_PUTVAR: {
41790  duk__debug_handle_put_var(thr, heap);
41791  break;
41792  }
41793  case DUK_DBG_CMD_GETCALLSTACK: {
41794  duk__debug_handle_get_call_stack(thr, heap);
41795  break;
41796  }
41797  case DUK_DBG_CMD_GETLOCALS: {
41798  duk__debug_handle_get_locals(thr, heap);
41799  break;
41800  }
41801  case DUK_DBG_CMD_EVAL: {
41802  duk__debug_handle_eval(thr, heap);
41803  break;
41804  }
41805  case DUK_DBG_CMD_DETACH: {
41806  /* The actual detached_cb call is postponed to message loop so
41807  * we don't need any special precautions here (just skip to EOM
41808  * on the already closed connection).
41809  */
41810  duk__debug_handle_detach(thr, heap);
41811  break;
41812  }
41813 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
41814  case DUK_DBG_CMD_DUMPHEAP: {
41815  duk__debug_handle_dump_heap(thr, heap);
41816  break;
41817  }
41818 #endif /* DUK_USE_DEBUGGER_DUMPHEAP */
41819  case DUK_DBG_CMD_GETBYTECODE: {
41820  duk__debug_handle_get_bytecode(thr, heap);
41821  break;
41822  }
41823  case DUK_DBG_CMD_APPREQUEST: {
41824  duk__debug_handle_apprequest(thr, heap);
41825  break;
41826  }
41827 #if defined(DUK_USE_DEBUGGER_INSPECT)
41828  case DUK_DBG_CMD_GETHEAPOBJINFO: {
41829  duk__debug_handle_get_heap_obj_info(thr, heap);
41830  break;
41831  }
41832  case DUK_DBG_CMD_GETOBJPROPDESC: {
41833  duk__debug_handle_get_obj_prop_desc(thr, heap);
41834  break;
41835  }
41836  case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
41837  duk__debug_handle_get_obj_prop_desc_range(thr, heap);
41838  break;
41839  }
41840 #endif /* DUK_USE_DEBUGGER_INSPECT */
41841  default: {
41842  DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
41843  duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
41844  }
41845  } /* switch cmd */
41846  break;
41847  }
41848  case DUK_DBG_IB_REPLY: {
41849  DUK_D(DUK_DPRINT("debug reply, skipping"));
41850  break;
41851  }
41852  case DUK_DBG_IB_ERROR: {
41853  DUK_D(DUK_DPRINT("debug error, skipping"));
41854  break;
41855  }
41856  case DUK_DBG_IB_NOTIFY: {
41857  DUK_D(DUK_DPRINT("debug notify, skipping"));
41858  break;
41859  }
41860  default: {
41861  DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
41862  goto fail;
41863  }
41864  } /* switch initial byte */
41865 
41866  DUK_ASSERT(duk_get_top(ctx) >= entry_top);
41867  duk_set_top(ctx, entry_top);
41868  duk__debug_skip_to_eom(thr);
41869  return;
41870 
41871  fail:
41872  DUK_ASSERT(duk_get_top(ctx) >= entry_top);
41873  duk_set_top(ctx, entry_top);
41874  DUK__SET_CONN_BROKEN(thr, 1);
41875  return;
41876 }
41877 
41878 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
41879  if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
41880  duk_debug_send_status(thr);
41881  thr->heap->dbg_state_dirty = 0;
41882  }
41883 }
41884 
41885 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
41886  duk_context *ctx = (duk_context *) thr;
41887 #if defined(DUK_USE_ASSERTIONS)
41888  duk_idx_t entry_top;
41889 #endif
41890  duk_bool_t retval = 0;
41891 
41892  DUK_ASSERT(thr != NULL);
41893  DUK_UNREF(ctx);
41894  DUK_ASSERT(thr->heap != NULL);
41895 #if defined(DUK_USE_ASSERTIONS)
41896  entry_top = duk_get_top(ctx);
41897 #endif
41898 
41899  DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
41900  thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
41901  (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
41902  DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(ctx)));
41903 
41904  /* thr->heap->dbg_detaching may be != 0 if a debugger write outside
41905  * the message loop caused a transport error and detach1() to run.
41906  */
41907  DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
41908  DUK_ASSERT(thr->heap->dbg_processing == 0);
41909  thr->heap->dbg_processing = 1;
41910 
41911  /* Ensure dirty state causes a Status even if never process any
41912  * messages. This is expected by the bytecode executor when in
41913  * the running state.
41914  */
41915  duk__check_resend_status(thr);
41916 
41917  for (;;) {
41918  /* Process messages until we're no longer paused or we peek
41919  * and see there's nothing to read right now.
41920  */
41921  DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(ctx)));
41922  DUK_ASSERT(thr->heap->dbg_processing == 1);
41923 
41924  while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
41925  /* Detach is pending; can be triggered from outside the
41926  * debugger loop (e.g. Status notify write error) or by
41927  * previous message handling. Call detached callback
41928  * here, in a controlled state, to ensure a possible
41929  * reattach inside the detached_cb is handled correctly.
41930  *
41931  * Recheck for detach in a while loop: an immediate
41932  * reattach involves a call to duk_debugger_attach()
41933  * which writes a debugger handshake line immediately
41934  * inside the API call. If the transport write fails
41935  * for that handshake, we can immediately end up in a
41936  * "transport broken, detaching" case several times here.
41937  * Loop back until we're either cleanly attached or
41938  * fully detached.
41939  *
41940  * NOTE: Reset dbg_processing = 1 forcibly, in case we
41941  * re-attached; duk_debugger_attach() sets dbg_processing
41942  * to 0 at the moment.
41943  */
41944 
41945  DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
41946 
41947  duk__debug_do_detach2(thr->heap);
41948  thr->heap->dbg_processing = 1; /* may be set to 0 by duk_debugger_attach() inside callback */
41949 
41950  DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
41951  thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
41952  }
41953  DUK_ASSERT(thr->heap->dbg_detaching == 0); /* true even with reattach */
41954  DUK_ASSERT(thr->heap->dbg_processing == 1); /* even after a detach and possible reattach */
41955 
41956  if (thr->heap->dbg_read_cb == NULL) {
41957  DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
41958  break;
41959  }
41960 
41961  if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
41962  if (!duk_debug_read_peek(thr)) {
41963  /* Note: peek cannot currently trigger a detach
41964  * so the dbg_detaching == 0 assert outside the
41965  * loop is correct.
41966  */
41967  DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
41968  break;
41969  }
41970  DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
41971  } else {
41972  DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
41973  }
41974 
41975  duk__check_resend_status(thr);
41976  duk__debug_process_message(thr);
41977  duk__check_resend_status(thr);
41978 
41979  retval = 1; /* processed one or more messages */
41980  }
41981 
41982  DUK_ASSERT(thr->heap->dbg_detaching == 0);
41983  DUK_ASSERT(thr->heap->dbg_processing == 1);
41984  thr->heap->dbg_processing = 0;
41985 
41986  /* As an initial implementation, read flush after exiting the message
41987  * loop. If transport is broken, this is a no-op (with debug logs).
41988  */
41989  duk_debug_read_flush(thr); /* this cannot initiate a detach */
41990  DUK_ASSERT(thr->heap->dbg_detaching == 0);
41991 
41992  DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(ctx)));
41993 
41994 #if defined(DUK_USE_ASSERTIONS)
41995  /* Easy to get wrong, so assert for it. */
41996  DUK_ASSERT(entry_top == duk_get_top(ctx));
41997 #endif
41998 
41999  return retval;
42000 }
42001 
42002 /*
42003  * Halt execution helper
42004  */
42005 
42006 /* Halt execution and enter a debugger message loop until execution is resumed
42007  * by the client. PC for the current activation may be temporarily decremented
42008  * so that the "current" instruction will be shown by the client. This helper
42009  * is callable from anywhere, also outside bytecode executor.
42010  */
42011 
42012 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
42013  duk_activation *act;
42014  duk_hcompfunc *fun;
42015  duk_instr_t *old_pc = NULL;
42016 
42017  DUK_ASSERT(thr != NULL);
42018  DUK_ASSERT(thr->heap != NULL);
42019  DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
42020  DUK_ASSERT(thr->heap->dbg_processing == 0);
42021 
42022  DUK_HEAP_SET_PAUSED(thr->heap);
42023 
42024  act = duk_hthread_get_current_activation(thr);
42025 
42026  /* NOTE: act may be NULL if an error is thrown outside of any activation,
42027  * which may happen in the case of, e.g. syntax errors.
42028  */
42029 
42030  /* Decrement PC if that was requested, this requires a PC sync. */
42031  if (act != NULL) {
42032  duk_hthread_sync_currpc(thr);
42033  old_pc = act->curr_pc;
42034  fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
42035 
42036  /* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
42037  * guaranteed to be a non-NULL Ecmascript function.
42038  */
42039  DUK_ASSERT(act->curr_pc == NULL ||
42040  (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
42041  if (use_prev_pc &&
42042  act->curr_pc != NULL &&
42043  act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
42044  act->curr_pc--;
42045  }
42046  }
42047 
42048  /* Process debug messages until we are no longer paused. */
42049 
42050  /* NOTE: This is a bit fragile. It's important to ensure that
42051  * duk_debug_process_messages() never throws an error or
42052  * act->curr_pc will never be reset.
42053  */
42054 
42055  thr->heap->dbg_state_dirty = 1;
42056  while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
42057  DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
42058  DUK_ASSERT(thr->heap->dbg_processing);
42059  duk_debug_process_messages(thr, 0 /*no_block*/);
42060  }
42061 
42062  /* XXX: Decrementing and restoring act->curr_pc works now, but if the
42063  * debugger message loop gains the ability to adjust the current PC
42064  * (e.g. a forced jump) restoring the PC here will break. Another
42065  * approach would be to use a state flag for the "decrement 1 from
42066  * topmost activation's PC" and take it into account whenever dealing
42067  * with PC values.
42068  */
42069  if (act != NULL) {
42070  act->curr_pc = old_pc; /* restore PC */
42071  }
42072 }
42073 
42074 /*
42075  * Breakpoint management
42076  */
42077 
42078 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
42079  duk_heap *heap;
42080  duk_breakpoint *b;
42081 
42082  /* Caller must trigger recomputation of active breakpoint list. To
42083  * ensure stale values are not used if that doesn't happen, clear the
42084  * active breakpoint list here.
42085  */
42086 
42087  DUK_ASSERT(thr != NULL);
42088  DUK_ASSERT(filename != NULL);
42089  heap = thr->heap;
42090  DUK_ASSERT(heap != NULL);
42091 
42092  if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
42093  DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
42094  (duk_heaphdr *) filename, (long) line));
42095  return -1;
42096  }
42097  heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
42098  b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
42099  b->filename = filename;
42100  b->line = line;
42101  DUK_HSTRING_INCREF(thr, filename);
42102 
42103  return heap->dbg_breakpoint_count - 1; /* index */
42104 }
42105 
42106 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
42107  duk_heap *heap;
42108  duk_hstring *h;
42109  duk_breakpoint *b;
42110  duk_size_t move_size;
42111 
42112  /* Caller must trigger recomputation of active breakpoint list. To
42113  * ensure stale values are not used if that doesn't happen, clear the
42114  * active breakpoint list here.
42115  */
42116 
42117  DUK_ASSERT(thr != NULL);
42118  heap = thr->heap;
42119  DUK_ASSERT(heap != NULL);
42120  DUK_ASSERT(DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap));
42121  DUK_ASSERT_DISABLE(breakpoint_index >= 0); /* unsigned */
42122 
42123  if (breakpoint_index >= heap->dbg_breakpoint_count) {
42124  DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
42125  return 0;
42126  }
42127  b = heap->dbg_breakpoints + breakpoint_index;
42128 
42129  h = b->filename;
42130  DUK_ASSERT(h != NULL);
42131 
42132  move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
42133  if (move_size > 0) {
42134  DUK_MEMMOVE((void *) b,
42135  (const void *) (b + 1),
42136  (size_t) move_size);
42137  }
42138  heap->dbg_breakpoint_count--;
42139  heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
42140 
42141  DUK_HSTRING_DECREF(thr, h); /* side effects */
42142  DUK_UNREF(h); /* w/o refcounting */
42143 
42144  /* Breakpoint entries above the used area are left as garbage. */
42145 
42146  return 1;
42147 }
42148 
42149 #else /* DUK_USE_DEBUGGER_SUPPORT */
42150 
42151 /* No debugger support. */
42152 
42153 #endif /* DUK_USE_DEBUGGER_SUPPORT */
42154 
42155 /* automatic undefs */
42156 #undef DUK__SET_CONN_BROKEN
42157 /*
42158  * Augmenting errors at their creation site and their throw site.
42159  *
42160  * When errors are created, traceback data is added by built-in code
42161  * and a user error handler (if defined) can process or replace the
42162  * error. Similarly, when errors are thrown, a user error handler
42163  * (if defined) can process or replace the error.
42164  *
42165  * Augmentation and other processing at error creation time is nice
42166  * because an error is only created once, but it may be thrown and
42167  * rethrown multiple times. User error handler registered for processing
42168  * an error at its throw site must be careful to handle rethrowing in
42169  * a useful manner.
42170  *
42171  * Error augmentation may throw an internal error (e.g. alloc error).
42172  *
42173  * Ecmascript allows throwing any values, so all values cannot be
42174  * augmented. Currently, the built-in augmentation at error creation
42175  * only augments error values which are Error instances (= have the
42176  * built-in Error.prototype in their prototype chain) and are also
42177  * extensible. User error handlers have no limitations in this respect.
42178  */
42179 
42180 /* #include duk_internal.h -> already included */
42181 
42182 /*
42183  * Helper for calling a user error handler.
42184  *
42185  * 'thr' must be the currently active thread; the error handler is called
42186  * in its context. The valstack of 'thr' must have the error value on
42187  * top, and will be replaced by another error value based on the return
42188  * value of the error handler.
42189  *
42190  * The helper calls duk_handle_call() recursively in protected mode.
42191  * Before that call happens, no longjmps should happen; as a consequence,
42192  * we must assume that the valstack contains enough temporary space for
42193  * arguments and such.
42194  *
42195  * While the error handler runs, any errors thrown will not trigger a
42196  * recursive error handler call (this is implemented using a heap level
42197  * flag which will "follow" through any coroutines resumed inside the
42198  * error handler). If the error handler is not callable or throws an
42199  * error, the resulting error replaces the original error (for Duktape
42200  * internal errors, duk_error_throw.c further substitutes this error with
42201  * a DoubleError which is not ideal). This would be easy to change and
42202  * even signal to the caller.
42203  *
42204  * The user error handler is stored in 'Duktape.errCreate' or
42205  * 'Duktape.errThrow' depending on whether we're augmenting the error at
42206  * creation or throw time. There are several alternatives to this approach,
42207  * see doc/error-objects.rst for discussion.
42208  *
42209  * Note: since further longjmp()s may occur while calling the error handler
42210  * (for many reasons, e.g. a labeled 'break' inside the handler), the
42211  * caller can make no assumptions on the thr->heap->lj state after the
42212  * call (this affects especially duk_error_throw.c). This is not an issue
42213  * as long as the caller writes to the lj state only after the error handler
42214  * finishes.
42215  */
42216 
42217 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
42218 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
42219  duk_context *ctx = (duk_context *) thr;
42220  duk_tval *tv_hnd;
42221  duk_small_uint_t call_flags;
42222  duk_int_t rc;
42223 
42224  DUK_ASSERT(thr != NULL);
42225  DUK_ASSERT(thr->heap != NULL);
42226  DUK_ASSERT_STRIDX_VALID(stridx_cb);
42227 
42228  if (DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap)) {
42229  DUK_DD(DUK_DDPRINT("recursive call to error handler, ignore"));
42230  return;
42231  }
42232 
42233  /*
42234  * Check whether or not we have an error handler.
42235  *
42236  * We must be careful of not triggering an error when looking up the
42237  * property. For instance, if the property is a getter, we don't want
42238  * to call it, only plain values are allowed. The value, if it exists,
42239  * is not checked. If the value is not a function, a TypeError happens
42240  * when it is called and that error replaces the original one.
42241  */
42242 
42243  DUK_ASSERT_VALSTACK_SPACE(thr, 4); /* 3 entries actually needed below */
42244 
42245  /* [ ... errval ] */
42246 
42247  if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
42248  /* When creating built-ins, some of the built-ins may not be set
42249  * and we want to tolerate that when throwing errors.
42250  */
42251  DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
42252  return;
42253  }
42254  tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
42255  thr->builtins[DUK_BIDX_DUKTAPE],
42256  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
42257  if (tv_hnd == NULL) {
42258  DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
42259  (duk_tval *) tv_hnd));
42260  return;
42261  }
42262  DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
42263  (duk_tval *) tv_hnd));
42264  duk_push_tval(ctx, tv_hnd);
42265 
42266  /* [ ... errval errhandler ] */
42267 
42268  duk_insert(ctx, -2); /* -> [ ... errhandler errval ] */
42269  duk_push_undefined(ctx);
42270  duk_insert(ctx, -2); /* -> [ ... errhandler undefined(= this) errval ] */
42271 
42272  /* [ ... errhandler undefined errval ] */
42273 
42274  /*
42275  * DUK_CALL_FLAG_IGNORE_RECLIMIT causes duk_handle_call() to ignore C
42276  * recursion depth limit (and won't increase it either). This is
42277  * dangerous, but useful because it allows the error handler to run
42278  * even if the original error is caused by C recursion depth limit.
42279  *
42280  * The heap level DUK_HEAP_FLAG_ERRHANDLER_RUNNING is set for the
42281  * duration of the error handler and cleared afterwards. This flag
42282  * prevents the error handler from running recursively. The flag is
42283  * heap level so that the flag properly controls even coroutines
42284  * launched by an error handler. Since the flag is heap level, it is
42285  * critical to restore it correctly.
42286  *
42287  * We ignore errors now: a success return and an error value both
42288  * replace the original error value. (This would be easy to change.)
42289  */
42290 
42291  DUK_ASSERT(!DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap)); /* since no recursive error handler calls */
42292  DUK_HEAP_SET_ERRHANDLER_RUNNING(thr->heap);
42293 
42294  call_flags = DUK_CALL_FLAG_IGNORE_RECLIMIT; /* ignore reclimit, not constructor */
42295 
42296  rc = duk_handle_call_protected(thr,
42297  1, /* num args */
42298  call_flags); /* call_flags */
42299  DUK_UNREF(rc); /* no need to check now: both success and error are OK */
42300 
42301  DUK_ASSERT(DUK_HEAP_HAS_ERRHANDLER_RUNNING(thr->heap));
42302  DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(thr->heap);
42303 
42304  /* [ ... errval ] */
42305 }
42306 #endif /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
42307 
42308 /*
42309  * Add ._Tracedata to an error on the stack top.
42310  */
42311 
42312 #if defined(DUK_USE_TRACEBACKS)
42313 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) {
42314  duk_context *ctx = (duk_context *) thr;
42315  duk_small_uint_t depth;
42316  duk_int_t i, i_min;
42317  duk_int_t arr_size;
42318  duk_harray *a;
42319  duk_tval *tv;
42320  duk_hstring *s;
42321  duk_uint32_t u32;
42322  duk_double_t d;
42323 
42324  DUK_ASSERT(thr != NULL);
42325  DUK_ASSERT(thr_callstack != NULL);
42326  DUK_ASSERT(ctx != NULL);
42327 
42328  /* [ ... error ] */
42329 
42330  /*
42331  * The traceback format is pretty arcane in an attempt to keep it compact
42332  * and cheap to create. It may change arbitrarily from version to version.
42333  * It should be decoded/accessed through version specific accessors only.
42334  *
42335  * See doc/error-objects.rst.
42336  */
42337 
42338  DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
42339  (duk_tval *) duk_get_tval(ctx, -1)));
42340 
42341  /* Preallocate array to correct size, so that we can just write out
42342  * the _Tracedata values into the array part.
42343  */
42344  depth = DUK_USE_TRACEBACK_DEPTH;
42345  arr_size = (duk_int_t) (thr_callstack->callstack_top <= depth ? thr_callstack->callstack_top : depth) * 2;
42346  if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
42347  arr_size += 2;
42348  }
42349  if (c_filename) {
42350  /* We need the C filename to be interned before getting the
42351  * array part pointer to avoid any GC interference while the
42352  * array part is populated.
42353  */
42354  duk_push_string(ctx, c_filename);
42355  arr_size += 2;
42356  }
42357 
42358  DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
42359  a = duk_push_harray_with_size(ctx, (duk_uint32_t) arr_size); /* XXX: call which returns array part pointer directly */
42360  DUK_ASSERT(a != NULL);
42361  tv = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
42362  DUK_ASSERT(tv != NULL || arr_size == 0);
42363 
42364  /* Compiler SyntaxErrors (and other errors) come first, and are
42365  * blamed by default (not flagged "noblame").
42366  */
42367  if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
42368  s = thr->compile_ctx->h_filename;
42369  DUK_TVAL_SET_STRING(tv, s);
42370  DUK_HSTRING_INCREF(thr, s);
42371  tv++;
42372 
42373  u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line; /* (flags<<32) + (line), flags = 0 */
42374  DUK_TVAL_SET_U32(tv, u32);
42375  tv++;
42376  }
42377 
42378  /* Filename/line from C macros (__FILE__, __LINE__) are added as an
42379  * entry with a special format: (string, number). The number contains
42380  * the line and flags.
42381  */
42382 
42383  /* [ ... error c_filename? arr ] */
42384 
42385  if (c_filename) {
42386  DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
42387  s = DUK_TVAL_GET_STRING(thr->valstack_top - 2); /* interned c_filename */
42388  DUK_ASSERT(s != NULL);
42389  DUK_TVAL_SET_STRING(tv, s);
42390  DUK_HSTRING_INCREF(thr, s);
42391  tv++;
42392 
42393  d = (noblame_fileline ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
42394  (duk_double_t) c_line;
42395  DUK_TVAL_SET_DOUBLE(tv, d);
42396  tv++;
42397  }
42398 
42399  /* traceback depth doesn't take into account the filename/line
42400  * special handling above (intentional)
42401  */
42402  depth = DUK_USE_TRACEBACK_DEPTH;
42403  i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
42404  DUK_ASSERT(i_min >= 0);
42405 
42406  /* [ ... error c_filename? arr ] */
42407 
42408  DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
42409  for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
42410  duk_uint32_t pc;
42411  duk_tval *tv_src;
42412 
42413  /*
42414  * Note: each API operation potentially resizes the callstack,
42415  * so be careful to re-lookup after every operation. Currently
42416  * these is no issue because we don't store a temporary 'act'
42417  * pointer at all. (This would be a non-issue if we operated
42418  * directly on the array part.)
42419  */
42420 
42421  /* [... arr] */
42422 
42423  DUK_ASSERT_DISABLE(thr_callstack->callstack[i].pc >= 0); /* unsigned */
42424 
42425  /* Add function object. */
42426  tv_src = &(thr_callstack->callstack + i)->tv_func; /* object (function) or lightfunc */
42427  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
42428  DUK_TVAL_SET_TVAL(tv, tv_src);
42429  DUK_TVAL_INCREF(thr, tv);
42430  tv++;
42431 
42432  /* Add a number containing: pc, activation flags.
42433  *
42434  * PC points to next instruction, find offending PC. Note that
42435  * PC == 0 for native code.
42436  */
42437  pc = duk_hthread_get_act_prev_pc(thr_callstack, thr_callstack->callstack + i);
42438  DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
42439  DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
42440  d = ((duk_double_t) thr_callstack->callstack[i].flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
42441  DUK_TVAL_SET_DOUBLE(tv, d);
42442  tv++;
42443  }
42444 
42445  DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
42446  DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
42447 
42448  /* [ ... error c_filename? arr ] */
42449 
42450  if (c_filename) {
42451  duk_remove_m2(ctx);
42452  }
42453 
42454  /* [ ... error arr ] */
42455 
42456  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INT_TRACEDATA); /* -> [ ... error ] */
42457 }
42458 #endif /* DUK_USE_TRACEBACKS */
42459 
42460 /*
42461  * Add .fileName and .lineNumber to an error on the stack top.
42462  */
42463 
42464 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
42465 DUK_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) {
42466  duk_context *ctx;
42467 #if defined(DUK_USE_ASSERTIONS)
42468  duk_int_t entry_top;
42469 #endif
42470 
42471  ctx = (duk_context *) thr;
42472 #if defined(DUK_USE_ASSERTIONS)
42473  entry_top = duk_get_top(ctx);
42474 #endif
42475 
42476  /*
42477  * If tracebacks are disabled, 'fileName' and 'lineNumber' are added
42478  * as plain own properties. Since Error.prototype has accessors of
42479  * the same name, we need to define own properties directly (cannot
42480  * just use e.g. duk_put_prop_stridx). Existing properties are not
42481  * overwritten in case they already exist.
42482  */
42483 
42484  if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
42485  /* Compiler SyntaxError (or other error) gets the primary blame.
42486  * Currently no flag to prevent blaming.
42487  */
42488  duk_push_uint(ctx, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
42489  duk_push_hstring(ctx, thr->compile_ctx->h_filename);
42490  } else if (c_filename && !noblame_fileline) {
42491  /* C call site gets blamed next, unless flagged not to do so.
42492  * XXX: file/line is disabled in minimal builds, so disable this
42493  * too when appropriate.
42494  */
42495  duk_push_int(ctx, c_line);
42496  duk_push_string(ctx, c_filename);
42497  } else {
42498  /* Finally, blame the innermost callstack entry which has a
42499  * .fileName property.
42500  */
42501  duk_small_uint_t depth;
42502  duk_int_t i, i_min;
42503  duk_uint32_t ecma_line;
42504 
42505  depth = DUK_USE_TRACEBACK_DEPTH;
42506  i_min = (thr_callstack->callstack_top > (duk_size_t) depth ? (duk_int_t) (thr_callstack->callstack_top - depth) : 0);
42507  DUK_ASSERT(i_min >= 0);
42508 
42509  DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX); /* callstack limits */
42510  for (i = (duk_int_t) (thr_callstack->callstack_top - 1); i >= i_min; i--) {
42511  duk_activation *act;
42512  duk_hobject *func;
42513  duk_uint32_t pc;
42514 
42515  DUK_UNREF(pc);
42516  act = thr_callstack->callstack + i;
42517  DUK_ASSERT(act >= thr_callstack->callstack && act < thr_callstack->callstack + thr_callstack->callstack_size);
42518 
42519  func = DUK_ACT_GET_FUNC(act);
42520  if (func == NULL) {
42521  /* Lightfunc, not blamed now. */
42522  continue;
42523  }
42524 
42525  /* PC points to next instruction, find offending PC,
42526  * PC == 0 for native code.
42527  */
42528  pc = duk_hthread_get_act_prev_pc(thr, act); /* thr argument only used for thr->heap, so specific thread doesn't matter */
42529  DUK_ASSERT_DISABLE(pc >= 0); /* unsigned */
42530  DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32); /* assume PC is at most 32 bits and non-negative */
42531  act = NULL; /* invalidated by pushes, so get out of the way */
42532 
42533  duk_push_hobject(ctx, func);
42534 
42535  /* [ ... error func ] */
42536 
42537  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_FILE_NAME);
42538  if (!duk_is_string_notsymbol(ctx, -1)) {
42539  duk_pop_2(ctx);
42540  continue;
42541  }
42542 
42543  /* [ ... error func fileName ] */
42544 
42545  ecma_line = 0;
42546 #if defined(DUK_USE_PC2LINE)
42547  if (DUK_HOBJECT_IS_COMPFUNC(func)) {
42548  ecma_line = duk_hobject_pc2line_query(ctx, -2, (duk_uint_fast32_t) pc);
42549  } else {
42550  /* Native function, no relevant lineNumber. */
42551  }
42552 #endif /* DUK_USE_PC2LINE */
42553  duk_push_u32(ctx, ecma_line);
42554 
42555  /* [ ... error func fileName lineNumber ] */
42556 
42557  duk_replace(ctx, -3);
42558 
42559  /* [ ... error lineNumber fileName ] */
42560  goto define_props;
42561  }
42562 
42563  /* No activation matches, use undefined for both .fileName and
42564  * .lineNumber (matches what we do with a _Tracedata based
42565  * no-match lookup.
42566  */
42567  duk_push_undefined(ctx);
42568  duk_push_undefined(ctx);
42569  }
42570 
42571  define_props:
42572  /* [ ... error lineNumber fileName ] */
42573 #if defined(DUK_USE_ASSERTIONS)
42574  DUK_ASSERT(duk_get_top(ctx) == entry_top + 2);
42575 #endif
42576  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
42577  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
42578 }
42579 #endif /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
42580 
42581 /*
42582  * Add line number to a compiler error.
42583  */
42584 
42585 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
42586 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
42587  duk_context *ctx;
42588 
42589  /* Append a "(line NNN)" to the "message" property of any error
42590  * thrown during compilation. Usually compilation errors are
42591  * SyntaxErrors but they can also be out-of-memory errors and
42592  * the like.
42593  */
42594 
42595  /* [ ... error ] */
42596 
42597  ctx = (duk_context *) thr;
42598  DUK_ASSERT(duk_is_object(ctx, -1));
42599 
42600  if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
42601  return;
42602  }
42603 
42604  DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
42605  (duk_tval *) duk_get_tval(ctx, -1)));
42606 
42607  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_MESSAGE)) {
42608  duk_push_sprintf(ctx, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
42609  duk_concat(ctx, 2);
42610  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_MESSAGE);
42611  } else {
42612  duk_pop(ctx);
42613  }
42614 
42615  DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
42616  (duk_tval *) duk_get_tval(ctx, -1)));
42617 }
42618 #endif /* DUK_USE_AUGMENT_ERROR_CREATE */
42619 
42620 /*
42621  * Augment an error being created using Duktape specific properties
42622  * like _Tracedata or .fileName/.lineNumber.
42623  */
42624 
42625 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
42626 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) {
42627  duk_context *ctx = (duk_context *) thr;
42628 #if defined(DUK_USE_ASSERTIONS)
42629  duk_int_t entry_top;
42630 #endif
42631 
42632 #if defined(DUK_USE_ASSERTIONS)
42633  entry_top = duk_get_top(ctx);
42634 #endif
42635  DUK_ASSERT(obj != NULL);
42636 
42637  DUK_UNREF(obj); /* unreferenced w/o tracebacks */
42638  DUK_UNREF(ctx); /* unreferenced w/o asserts */
42639 
42640  duk__add_compiler_error_line(thr);
42641 
42642 #if defined(DUK_USE_TRACEBACKS)
42643  /* If tracebacks are enabled, the '_Tracedata' property is the only
42644  * thing we need: 'fileName' and 'lineNumber' are virtual properties
42645  * which use '_Tracedata'.
42646  */
42647  if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
42648  DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
42649  } else {
42650  duk__add_traceback(thr, thr_callstack, c_filename, c_line, noblame_fileline);
42651  }
42652 #else
42653  /* Without tracebacks the concrete .fileName and .lineNumber need
42654  * to be added directly.
42655  */
42656  duk__add_fileline(thr, thr_callstack, c_filename, c_line, noblame_fileline);
42657 #endif
42658 
42659 #if defined(DUK_USE_ASSERTIONS)
42660  DUK_ASSERT(duk_get_top(ctx) == entry_top);
42661 #endif
42662 }
42663 #endif /* DUK_USE_AUGMENT_ERROR_CREATE */
42664 
42665 /*
42666  * Augment an error at creation time with _Tracedata/fileName/lineNumber
42667  * and allow a user error handler (if defined) to process/replace the error.
42668  * The error to be augmented is at the stack top.
42669  *
42670  * thr: thread containing the error value
42671  * thr_callstack: thread which should be used for generating callstack etc.
42672  * c_filename: C __FILE__ related to the error
42673  * c_line: C __LINE__ related to the error
42674  * noblame_fileline: if true, don't fileName/line as error source, otherwise use traceback
42675  * (needed because user code filename/line are reported but internal ones
42676  * are not)
42677  *
42678  * XXX: rename noblame_fileline to flags field; combine it to some existing
42679  * field (there are only a few call sites so this may not be worth it).
42680  */
42681 
42682 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
42683 DUK_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) {
42684  duk_context *ctx = (duk_context *) thr;
42685  duk_hobject *obj;
42686 
42687  DUK_ASSERT(thr != NULL);
42688  DUK_ASSERT(thr_callstack != NULL);
42689  DUK_ASSERT(ctx != NULL);
42690 
42691  /* [ ... error ] */
42692 
42693  /*
42694  * Criteria for augmenting:
42695  *
42696  * - augmentation enabled in build (naturally)
42697  * - error value internal prototype chain contains the built-in
42698  * Error prototype object (i.e. 'val instanceof Error')
42699  *
42700  * Additional criteria for built-in augmenting:
42701  *
42702  * - error value is an extensible object
42703  */
42704 
42705  obj = duk_get_hobject(ctx, -1);
42706  if (!obj) {
42707  DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
42708  return;
42709  }
42710  if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
42711  /* If the value has a prototype loop, it's critical not to
42712  * throw here. Instead, assume the value is not to be
42713  * augmented.
42714  */
42715  DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
42716  return;
42717  }
42718  if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
42719  DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
42720  duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, noblame_fileline, obj);
42721  } else {
42722  DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
42723  }
42724 
42725  /* [ ... error ] */
42726 
42727 #if defined(DUK_USE_ERRCREATE)
42728  duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
42729 #endif
42730 }
42731 #endif /* DUK_USE_AUGMENT_ERROR_CREATE */
42732 
42733 /*
42734  * Augment an error at throw time; allow a user error handler (if defined)
42735  * to process/replace the error. The error to be augmented is at the
42736  * stack top.
42737  */
42738 
42739 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
42740 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
42741 #if defined(DUK_USE_ERRTHROW)
42742  duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
42743 #endif /* DUK_USE_ERRTHROW */
42744 }
42745 #endif /* DUK_USE_AUGMENT_ERROR_THROW */
42746 /*
42747  * Do a longjmp call, calling the fatal error handler if no
42748  * catchpoint exists.
42749  */
42750 
42751 /* #include duk_internal.h -> already included */
42752 
42753 #if defined(DUK_USE_PREFER_SIZE)
42754 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
42755  (void) duk_fatal((duk_context *) thr, "uncaught error");
42756 }
42757 #endif
42758 
42759 #if 0
42760 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
42761  const char *summary;
42762  char buf[64];
42763 
42764  summary = duk_push_string_tval_readable((duk_context *) thr, &thr->heap->lj.value1);
42765  DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
42766  buf[sizeof(buf) - 1] = (char) 0;
42767  (void) duk_fatal((duk_context *) thr, (const char *) buf);
42768 }
42769 #endif
42770 
42771 #if !defined(DUK_USE_PREFER_SIZE)
42772 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
42773  const char *summary;
42774  char buf[64];
42775 
42776  summary = duk_push_string_tval_readable_error((duk_context *) thr, &thr->heap->lj.value1);
42777  DUK_ASSERT(summary != NULL);
42778  DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
42779  buf[sizeof(buf) - 1] = (char) 0;
42780  (void) duk_fatal((duk_context *) thr, (const char *) buf);
42781 }
42782 #endif
42783 
42784 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
42785  DUK_ASSERT(thr != NULL);
42786 
42787  DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
42788  (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
42789  &thr->heap->lj.value1, &thr->heap->lj.value2));
42790 
42791  /* Perform a refzero check before throwing: this catches cases where
42792  * some internal code uses no-refzero (NORZ) macro variants but an
42793  * error occurs before it has the chance to DUK_REFZERO_CHECK_xxx()
42794  * explicitly. Refzero'ed objects would otherwise remain pending
42795  * until the next refzero (which is not a big issue but still).
42796  */
42797  DUK_REFZERO_CHECK_SLOW(thr);
42798 
42799 #if !defined(DUK_USE_CPP_EXCEPTIONS)
42800  /* If we don't have a jmpbuf_ptr, there is little we can do except
42801  * cause a fatal error. The caller's expectation is that we never
42802  * return.
42803  *
42804  * With C++ exceptions we now just propagate an uncaught error
42805  * instead of invoking the fatal error handler. Because there's
42806  * a dummy jmpbuf for C++ exceptions now, this could be changed.
42807  */
42808  if (!thr->heap->lj.jmpbuf_ptr) {
42809  DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
42810  (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
42811  &thr->heap->lj.value1, &thr->heap->lj.value2));
42812 
42813 #if defined(DUK_USE_PREFER_SIZE)
42814  duk__uncaught_minimal(thr);
42815 #else
42816  duk__uncaught_error_aware(thr);
42817 #endif
42818  DUK_UNREACHABLE();
42819  }
42820 #endif /* DUK_USE_CPP_EXCEPTIONS */
42821 
42822 #if defined(DUK_USE_CPP_EXCEPTIONS)
42823  {
42824  duk_internal_exception exc; /* dummy */
42825  throw exc;
42826  }
42827 #else /* DUK_USE_CPP_EXCEPTIONS */
42828  DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
42829 #endif /* DUK_USE_CPP_EXCEPTIONS */
42830 
42831  DUK_UNREACHABLE();
42832 }
42833 /*
42834  * Error helpers
42835  */
42836 
42837 /* #include duk_internal.h -> already included */
42838 
42839 /*
42840  * Helper to walk the thread chain and see if there is an active error
42841  * catcher. Protected calls or finally blocks aren't considered catching.
42842  */
42843 
42844 #if defined(DUK_USE_DEBUGGER_SUPPORT) && \
42845  (defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT))
42846 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
42847  /*
42848  * XXX: As noted above, a protected API call won't be counted as a
42849  * catcher. This is usually convenient, e.g. in the case of a top-
42850  * level duk_pcall(), but may not always be desirable. Perhaps add an
42851  * argument to treat them as catchers?
42852  */
42853 
42854  duk_size_t i;
42855 
42856  DUK_ASSERT(thr != NULL);
42857 
42858  while (thr != NULL) {
42859  for (i = 0; i < thr->catchstack_top; i++) {
42860  duk_catcher *cat = thr->catchstack + i;
42861  if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
42862  return 1; /* all we need to know */
42863  }
42864  }
42865  thr = thr->resumer;
42866  }
42867  return 0;
42868 }
42869 #endif /* DUK_USE_DEBUGGER_SUPPORT && (DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT) */
42870 
42871 /*
42872  * Get prototype object for an integer error code.
42873  */
42874 
42875 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
42876  switch (code) {
42877  case DUK_ERR_EVAL_ERROR:
42878  return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
42879  case DUK_ERR_RANGE_ERROR:
42880  return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
42881  case DUK_ERR_REFERENCE_ERROR:
42882  return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
42883  case DUK_ERR_SYNTAX_ERROR:
42884  return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
42885  case DUK_ERR_TYPE_ERROR:
42886  return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
42887  case DUK_ERR_URI_ERROR:
42888  return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
42889  case DUK_ERR_ERROR:
42890  default:
42891  return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
42892  }
42893 }
42894 
42895 /*
42896  * Exposed helper for setting up heap longjmp state.
42897  */
42898 
42899 DUK_INTERNAL void duk_err_setup_heap_ljstate(duk_hthread *thr, duk_small_int_t lj_type) {
42900 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42901  /* If something is thrown with the debugger attached and nobody will
42902  * catch it, execution is paused before the longjmp, turning over
42903  * control to the debug client. This allows local state to be examined
42904  * before the stack is unwound. Errors are not intercepted when debug
42905  * message loop is active (e.g. for Eval).
42906  */
42907 
42908  /* XXX: Allow customizing the pause and notify behavior at runtime
42909  * using debugger runtime flags. For now the behavior is fixed using
42910  * config options.
42911  */
42912 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY) || defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
42913  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) &&
42914  !thr->heap->dbg_processing &&
42915  lj_type == DUK_LJ_TYPE_THROW) {
42916  duk_context *ctx = (duk_context *) thr;
42917  duk_bool_t fatal;
42918  duk_hobject *h_obj;
42919 
42920  /* Don't intercept a DoubleError, we may have caused the initial double
42921  * fault and attempting to intercept it will cause us to be called
42922  * recursively and exhaust the C stack.
42923  */
42924  h_obj = duk_get_hobject(ctx, -1);
42925  if (h_obj == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
42926  DUK_D(DUK_DPRINT("built-in DoubleError instance thrown, not intercepting"));
42927  goto skip_throw_intercept;
42928  }
42929 
42930  DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
42931 
42932  fatal = !duk__have_active_catcher(thr);
42933 
42934 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
42935  /* Report it to the debug client */
42936  duk_debug_send_throw(thr, fatal);
42937 #endif
42938 
42939 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
42940  if (fatal) {
42941  DUK_D(DUK_DPRINT("throw will be fatal, halt before longjmp"));
42942  duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
42943  }
42944 #endif
42945  }
42946 
42947  skip_throw_intercept:
42948 #endif /* DUK_USE_DEBUGGER_THROW_NOTIFY || DUK_USE_DEBUGGER_PAUSE_UNCAUGHT */
42949 #endif /* DUK_USE_DEBUGGER_SUPPORT */
42950 
42951  thr->heap->lj.type = lj_type;
42952 
42953  DUK_ASSERT(thr->valstack_top > thr->valstack);
42954  DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, thr->valstack_top - 1); /* side effects */
42955 
42956  duk_pop((duk_context *) thr);
42957 }
42958 /*
42959  * Create and throw an Ecmascript error object based on a code and a message.
42960  *
42961  * Used when we throw errors internally. Ecmascript generated error objects
42962  * are created by Ecmascript code, and the throwing is handled by the bytecode
42963  * executor.
42964  */
42965 
42966 /* #include duk_internal.h -> already included */
42967 
42968 /*
42969  * Create and throw an error (originating from Duktape internally)
42970  *
42971  * Push an error object on top of the stack, possibly throw augmenting
42972  * the error, and finally longjmp.
42973  *
42974  * If an error occurs while we're dealing with the current error, we might
42975  * enter an infinite recursion loop. This is prevented by detecting a
42976  * "double fault" through the heap->handling_error flag; the recursion
42977  * then stops at the second level.
42978  */
42979 
42980 #if defined(DUK_USE_VERBOSE_ERRORS)
42981 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) {
42982 #else
42983 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
42984 #endif
42985  duk_context *ctx = (duk_context *) thr;
42986  duk_bool_t double_error = thr->heap->handling_error;
42987 
42988 #if defined(DUK_USE_VERBOSE_ERRORS)
42989  DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
42990  (long) code, (const char *) msg,
42991  (const char *) filename, (long) line));
42992 #else
42993  DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
42994 #endif
42995 
42996  DUK_ASSERT(thr != NULL);
42997  DUK_ASSERT(ctx != NULL);
42998 
42999  thr->heap->handling_error = 1;
43000 
43001  if (!double_error) {
43002  /* Allow headroom for calls during error handling (see GH-191).
43003  * We allow space for 10 additional recursions, with one extra
43004  * for, e.g. a print() call at the deepest level.
43005  */
43006  DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX);
43007  thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11;
43008  }
43009 
43010  DUK_ASSERT(thr->callstack_max == DUK_CALLSTACK_DEFAULT_MAX + DUK_CALLSTACK_GROW_STEP + 11); /* just making sure */
43011 
43012  /* Sync so that augmentation sees up-to-date activations, NULL
43013  * thr->ptr_curr_pc so that it's not used if side effects occur
43014  * in augmentation or longjmp handling.
43015  */
43016  duk_hthread_sync_and_null_currpc(thr);
43017 
43018  /*
43019  * Create and push an error object onto the top of stack.
43020  * If a "double error" occurs, use a fixed error instance
43021  * to avoid further trouble.
43022  */
43023 
43024  /* XXX: if attempt to push beyond allocated valstack, this double fault
43025  * handling fails miserably. We should really write the double error
43026  * directly to thr->heap->lj.value1 and avoid valstack use entirely.
43027  */
43028 
43029  if (double_error) {
43030  if (thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
43031  DUK_D(DUK_DPRINT("double fault detected -> push built-in fixed 'double error' instance"));
43032  duk_push_hobject_bidx(ctx, DUK_BIDX_DOUBLE_ERROR);
43033  } else {
43034  DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
43035  "-> push the error code as a number"));
43036  duk_push_int(ctx, (duk_int_t) code);
43037  }
43038  } else {
43039  /* Error object is augmented at its creation here. */
43040  duk_require_stack(ctx, 1);
43041  /* XXX: unnecessary '%s' formatting here, but cannot use
43042  * 'msg' as a format string directly.
43043  */
43044 #if defined(DUK_USE_VERBOSE_ERRORS)
43045  duk_push_error_object_raw(ctx,
43046  code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
43047  filename,
43048  line,
43049  "%s",
43050  (const char *) msg);
43051 #else
43052  duk_push_error_object_raw(ctx,
43053  code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
43054  NULL,
43055  0,
43056  NULL);
43057 #endif
43058  }
43059 
43060  /*
43061  * Augment error (throw time), unless double error
43062  *
43063  * Note that an alloc error may happen during error augmentation.
43064  * This may happen both when the original error is an alloc error
43065  * and when it's something else. Because any error in augmentation
43066  * must be handled correctly anyway, there's no special check for
43067  * avoiding it for alloc errors (this differs from Duktape 1.x).
43068  */
43069 
43070  if (double_error) {
43071  DUK_D(DUK_DPRINT("double error: skip throw augmenting to avoid further trouble"));
43072  } else {
43073 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
43074  DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
43075  (duk_tval *) duk_get_tval(ctx, -1)));
43076  duk_err_augment_error_throw(thr);
43077 #endif
43078  }
43079 
43080  /*
43081  * Finally, longjmp
43082  */
43083 
43084  duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
43085 
43086  thr->callstack_max = DUK_CALLSTACK_DEFAULT_MAX; /* reset callstack limit */
43087  thr->heap->handling_error = 0;
43088 
43089  DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
43090  (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
43091 
43092  duk_err_longjmp(thr);
43093  DUK_UNREACHABLE();
43094 }
43095 
43096 /*
43097  * Helper for C function call negative return values.
43098  */
43099 
43100 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
43101  duk_context *ctx = (duk_context *) thr;
43102 
43103  DUK_ASSERT(thr != NULL);
43104  DUK_ASSERT(rc < 0);
43105 
43106  /*
43107  * The __FILE__ and __LINE__ information is intentionally not used in the
43108  * creation of the error object, as it isn't useful in the tracedata. The
43109  * tracedata still contains the function which returned the negative return
43110  * code, and having the file/line of this function isn't very useful.
43111  *
43112  * The error messages for DUK_RET_xxx shorthand are intentionally very
43113  * minimal: they're only really useful for low memory targets.
43114  */
43115 
43116  duk_error_raw(ctx, -rc, NULL, 0, "error (rc %ld)", (long) rc);
43117  DUK_UNREACHABLE();
43118 }
43119 /*
43120  * duk_hbuffer allocation and freeing.
43121  */
43122 
43123 /* #include duk_internal.h -> already included */
43124 
43125 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
43126  * (NULL on error). Write buffer data pointer to 'out_bufdata' (only if
43127  * allocation successful).
43128  */
43129 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
43130  duk_hbuffer *res = NULL;
43131  duk_size_t header_size;
43132  duk_size_t alloc_size;
43133 
43134  DUK_ASSERT(heap != NULL);
43135  DUK_ASSERT(out_bufdata != NULL);
43136 
43137  DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
43138 
43139  /* Size sanity check. Should not be necessary because caller is
43140  * required to check this, but we don't want to cause a segfault
43141  * if the size wraps either in duk_size_t computation or when
43142  * storing the size in a 16-bit field.
43143  */
43144  if (size > DUK_HBUFFER_MAX_BYTELEN) {
43145  DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
43146  return NULL; /* no need to write 'out_bufdata' */
43147  }
43148 
43149  if (flags & DUK_BUF_FLAG_EXTERNAL) {
43150  header_size = sizeof(duk_hbuffer_external);
43151  alloc_size = sizeof(duk_hbuffer_external);
43152  } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
43153  header_size = sizeof(duk_hbuffer_dynamic);
43154  alloc_size = sizeof(duk_hbuffer_dynamic);
43155  } else {
43156  header_size = sizeof(duk_hbuffer_fixed);
43157  alloc_size = sizeof(duk_hbuffer_fixed) + size;
43158  DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed)); /* no wrapping */
43159  }
43160 
43161  res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
43162  if (!res) {
43163  goto error;
43164  }
43165 
43166  /* zero everything unless requested not to do so */
43167 #if defined(DUK_USE_ZERO_BUFFER_DATA)
43168  DUK_MEMZERO((void *) res,
43169  (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
43170 #else
43171  DUK_MEMZERO((void *) res, header_size);
43172 #endif
43173 
43174  if (flags & DUK_BUF_FLAG_EXTERNAL) {
43176  h = (duk_hbuffer_external *) res;
43177  DUK_UNREF(h);
43178  *out_bufdata = NULL;
43179 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
43180 #if defined(DUK_USE_HEAPPTR16)
43181 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
43182 #else
43183  DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
43184 #endif
43185 #endif
43186  DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
43187  } else if (flags & DUK_BUF_FLAG_DYNAMIC) {
43189  void *ptr;
43190 
43191  if (size > 0) {
43192  DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL)); /* alloc external with size zero */
43193  DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
43194 #if defined(DUK_USE_ZERO_BUFFER_DATA)
43195  ptr = DUK_ALLOC_ZEROED(heap, size);
43196 #else
43197  ptr = DUK_ALLOC(heap, size);
43198 #endif
43199  if (!ptr) {
43200  /* Because size > 0, NULL check is correct */
43201  goto error;
43202  }
43203  *out_bufdata = ptr;
43204 
43205  DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
43206  } else {
43207  *out_bufdata = NULL;
43208 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
43209 #if defined(DUK_USE_HEAPPTR16)
43210 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
43211 #else
43212  DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
43213 #endif
43214 #endif
43215  DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
43216  }
43217  } else {
43218  *out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);
43219  }
43220 
43221  DUK_HBUFFER_SET_SIZE(res, size);
43222 
43223  DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
43224  if (flags & DUK_BUF_FLAG_DYNAMIC) {
43225  DUK_HBUFFER_SET_DYNAMIC(res);
43226  if (flags & DUK_BUF_FLAG_EXTERNAL) {
43227  DUK_HBUFFER_SET_EXTERNAL(res);
43228  }
43229  } else {
43230  DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
43231  }
43232  DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
43233 
43234  DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
43235  return res;
43236 
43237  error:
43238  DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
43239 
43240  DUK_FREE(heap, res);
43241  return NULL; /* no need to write 'out_bufdata' */
43242 }
43243 
43244 /* For indirect allocs. */
43245 
43246 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
43248  DUK_UNREF(heap);
43249  return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
43250 }
43251 /*
43252  * duk_hbuffer operations such as resizing and inserting/appending data to
43253  * a dynamic buffer.
43254  *
43255  * Append operations append to the end of the buffer and they are relatively
43256  * efficient: the buffer is grown with a "spare" part relative to the buffer
43257  * size to minimize reallocations. Insert operations need to move existing
43258  * data forward in the buffer with memmove() and are not very efficient.
43259  * They are used e.g. by the regexp compiler to "backpatch" regexp bytecode.
43260  */
43261 
43262 /* #include duk_internal.h -> already included */
43263 
43264 /*
43265  * Resizing
43266  */
43267 
43268 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
43269  void *res;
43270  duk_size_t prev_size;
43271 
43272  DUK_ASSERT(thr != NULL);
43273  DUK_ASSERT(buf != NULL);
43274  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
43275  DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
43276 
43277  /*
43278  * Maximum size check
43279  */
43280 
43281  if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
43282  DUK_ERROR_RANGE(thr, "buffer too long");
43283  }
43284 
43285  /*
43286  * Note: use indirect realloc variant just in case mark-and-sweep
43287  * (finalizers) might resize this same buffer during garbage
43288  * collection.
43289  */
43290 
43291  res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
43292  if (res != NULL || new_size == 0) {
43293  /* 'res' may be NULL if new allocation size is 0. */
43294 
43295  DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
43296  (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
43297  (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
43298  (void *) res,
43299  (long) new_size));
43300 
43301  /*
43302  * The entire allocated buffer area, regardless of actual used
43303  * size, is kept zeroed in resizes for simplicity. If the buffer
43304  * is grown, zero the new part.
43305  */
43306 
43307  prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
43308  if (new_size > prev_size) {
43309  DUK_ASSERT(new_size - prev_size > 0);
43310 #if defined(DUK_USE_ZERO_BUFFER_DATA)
43311  DUK_MEMZERO((void *) ((char *) res + prev_size),
43312  (duk_size_t) (new_size - prev_size));
43313 #endif
43314  }
43315 
43316  DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
43317  DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
43318  } else {
43319  DUK_ERROR_ALLOC_FAILED(thr);
43320  }
43321 
43322  DUK_ASSERT(res != NULL || new_size == 0);
43323 }
43324 
43325 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
43326  DUK_ASSERT(thr != NULL);
43327  DUK_ASSERT(buf != NULL);
43328  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
43329  DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
43330 
43331  duk_hbuffer_resize(thr, buf, 0);
43332 }
43333 /* #include duk_internal.h -> already included */
43334 
43335 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
43336 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
43337  duk_uint_t buf_size;
43338  duk_uint_t buf_avail;
43339 
43340  DUK_ASSERT(h_bufobj != NULL);
43341  DUK_ASSERT(h_bufobj->buf != NULL);
43342 
43343  buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
43344  if (h_bufobj->offset > buf_size) {
43345  /* Slice starting point is beyond current length. */
43346  return 0;
43347  }
43348  buf_avail = buf_size - h_bufobj->offset;
43349 
43350  return buf_avail >= len ? len : buf_avail;
43351 }
43352 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
43353 /*
43354  * duk_heap allocation and freeing.
43355  */
43356 
43357 /* #include duk_internal.h -> already included */
43358 
43359 #if defined(DUK_USE_ROM_STRINGS)
43360 /* Fixed seed value used with ROM strings. */
43361 #define DUK__FIXED_HASH_SEED 0xabcd1234
43362 #endif
43363 
43364 /*
43365  * Free a heap object.
43366  *
43367  * Free heap object and its internal (non-heap) pointers. Assumes that
43368  * caller has removed the object from heap allocated list or the string
43369  * intern table, and any weak references (which strings may have) have
43370  * been already dealt with.
43371  */
43372 
43373 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
43374  DUK_ASSERT(heap != NULL);
43375  DUK_ASSERT(h != NULL);
43376 
43377  DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
43378 
43379  if (DUK_HOBJECT_IS_COMPFUNC(h)) {
43380  duk_hcompfunc *f = (duk_hcompfunc *) h;
43381  DUK_UNREF(f);
43382  /* Currently nothing to free; 'data' is a heap object */
43383  } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
43384  duk_hnatfunc *f = (duk_hnatfunc *) h;
43385  DUK_UNREF(f);
43386  /* Currently nothing to free */
43387  } else if (DUK_HOBJECT_IS_THREAD(h)) {
43388  duk_hthread *t = (duk_hthread *) h;
43389  DUK_FREE(heap, t->valstack);
43390  DUK_FREE(heap, t->callstack);
43391  DUK_FREE(heap, t->catchstack);
43392  /* Don't free h->resumer because it exists in the heap.
43393  * Callstack entries also contain function pointers which
43394  * are not freed for the same reason.
43395  */
43396 
43397  /* XXX: with 'caller' property the callstack would need
43398  * to be unwound to update the 'caller' properties of
43399  * functions in the callstack.
43400  */
43401  }
43402  DUK_FREE(heap, (void *) h);
43403 }
43404 
43405 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
43406  DUK_ASSERT(heap != NULL);
43407  DUK_ASSERT(h != NULL);
43408 
43409  if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
43411  DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
43412  DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
43413  }
43414  DUK_FREE(heap, (void *) h);
43415 }
43416 
43417 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
43418  DUK_ASSERT(heap != NULL);
43419  DUK_ASSERT(h != NULL);
43420 
43421  DUK_UNREF(heap);
43422  DUK_UNREF(h);
43423 
43424 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
43425  if (DUK_HSTRING_HAS_EXTDATA(h)) {
43426  DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
43427  h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
43428  DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
43429  }
43430 #endif
43431  DUK_FREE(heap, (void *) h);
43432 }
43433 
43434 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
43435  DUK_ASSERT(heap);
43436  DUK_ASSERT(hdr);
43437 
43438  DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
43439 
43440  switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
43441  case DUK_HTYPE_STRING:
43442  duk_free_hstring(heap, (duk_hstring *) hdr);
43443  break;
43444  case DUK_HTYPE_OBJECT:
43445  duk_free_hobject(heap, (duk_hobject *) hdr);
43446  break;
43447  case DUK_HTYPE_BUFFER:
43448  duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
43449  break;
43450  default:
43451  DUK_UNREACHABLE();
43452  }
43453 
43454 }
43455 
43456 /*
43457  * Free the heap.
43458  *
43459  * Frees heap-related non-heap-tracked allocations such as the
43460  * string intern table; then frees the heap allocated objects;
43461  * and finally frees the heap structure itself. Reference counts
43462  * and GC markers are ignored (and not updated) in this process,
43463  * and finalizers won't be called.
43464  *
43465  * The heap pointer and heap object pointers must not be used
43466  * after this call.
43467  */
43468 
43469 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
43470  duk_heaphdr *curr;
43471  duk_heaphdr *next;
43472 
43473  curr = heap->heap_allocated;
43474  while (curr) {
43475  /* We don't log or warn about freeing zero refcount objects
43476  * because they may happen with finalizer processing.
43477  */
43478 
43479  DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
43480  (duk_heaphdr *) curr));
43481  next = DUK_HEAPHDR_GET_NEXT(heap, curr);
43482  duk_heap_free_heaphdr_raw(heap, curr);
43483  curr = next;
43484  }
43485 }
43486 
43487 #if defined(DUK_USE_REFERENCE_COUNTING)
43488 DUK_LOCAL void duk__free_refzero_list(duk_heap *heap) {
43489  duk_heaphdr *curr;
43490  duk_heaphdr *next;
43491 
43492  curr = heap->refzero_list;
43493  while (curr) {
43494  DUK_DDD(DUK_DDDPRINT("FINALFREE (refzero_list): %!iO",
43495  (duk_heaphdr *) curr));
43496  next = DUK_HEAPHDR_GET_NEXT(heap, curr);
43497  duk_heap_free_heaphdr_raw(heap, curr);
43498  curr = next;
43499  }
43500 }
43501 #endif
43502 
43503 DUK_LOCAL void duk__free_markandsweep_finalize_list(duk_heap *heap) {
43504  duk_heaphdr *curr;
43505  duk_heaphdr *next;
43506 
43507  curr = heap->finalize_list;
43508  while (curr) {
43509  DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
43510  (duk_heaphdr *) curr));
43511  next = DUK_HEAPHDR_GET_NEXT(heap, curr);
43512  duk_heap_free_heaphdr_raw(heap, curr);
43513  curr = next;
43514  }
43515 }
43516 
43517 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
43518  /* strings are only tracked by stringtable */
43519  duk_heap_free_strtab(heap);
43520 }
43521 
43522 #if defined(DUK_USE_FINALIZER_SUPPORT)
43523 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
43524  duk_hthread *thr;
43525  duk_heaphdr *curr;
43526  duk_uint_t round_no;
43527  duk_size_t count_all;
43528  duk_size_t count_finalized;
43529  duk_size_t curr_limit;
43530 
43531  DUK_ASSERT(heap != NULL);
43532  DUK_ASSERT(heap->heap_thread != NULL);
43533 
43534 #if defined(DUK_USE_REFERENCE_COUNTING)
43535  DUK_ASSERT(heap->refzero_list == NULL); /* refzero not running -> must be empty */
43536 #endif
43537  DUK_ASSERT(heap->finalize_list == NULL); /* mark-and-sweep not running -> must be empty */
43538 
43539  /* XXX: here again finalizer thread is the heap_thread which needs
43540  * to be coordinated with finalizer thread fixes.
43541  */
43542  thr = heap->heap_thread;
43543  DUK_ASSERT(thr != NULL);
43544 
43545  /* Prevent mark-and-sweep for the pending finalizers, also prevents
43546  * refzero handling from moving objects away from the heap_allocated
43547  * list. (The flag meaning is slightly abused here.)
43548  */
43549  DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
43550  DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
43551 
43552  curr_limit = 0; /* suppress warning, not used */
43553  for (round_no = 0; ; round_no++) {
43554  curr = heap->heap_allocated;
43555  count_all = 0;
43556  count_finalized = 0;
43557  while (curr) {
43558  count_all++;
43559  if (DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT) {
43560  /* Only objects in heap_allocated may have finalizers. Check that
43561  * the object itself has a _Finalizer property (own or inherited)
43562  * so that we don't execute finalizers for e.g. Proxy objects.
43563  */
43564  DUK_ASSERT(thr != NULL);
43565  DUK_ASSERT(curr != NULL);
43566 
43567  if (duk_hobject_hasprop_raw(thr, (duk_hobject *) curr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
43568  if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
43569  DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)); /* maps to finalizer 2nd argument */
43570  duk_hobject_run_finalizer(thr, (duk_hobject *) curr);
43571  count_finalized++;
43572  }
43573  }
43574  }
43575  curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
43576  }
43577 
43578  /* Each round of finalizer execution may spawn new finalizable objects
43579  * which is normal behavior for some applications. Allow multiple
43580  * rounds of finalization, but use a shrinking limit based on the
43581  * first round to detect the case where a runaway finalizer creates
43582  * an unbounded amount of new finalizable objects. Finalizer rescue
43583  * is not supported: the semantics are unclear because most of the
43584  * objects being finalized here are already reachable. The finalizer
43585  * is given a boolean to indicate that rescue is not possible.
43586  *
43587  * See discussion in: https://github.com/svaarala/duktape/pull/473
43588  */
43589 
43590  if (round_no == 0) {
43591  /* Cannot wrap: each object is at least 8 bytes so count is
43592  * at most 1/8 of that.
43593  */
43594  curr_limit = count_all * 2;
43595  } else {
43596  curr_limit = (curr_limit * 3) / 4; /* Decrease by 25% every round */
43597  }
43598  DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
43599  (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
43600 
43601  if (count_finalized == 0) {
43602  DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
43603  break;
43604  }
43605  if (count_finalized >= curr_limit) {
43606  DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
43607  break;
43608  }
43609  }
43610 
43611  DUK_ASSERT(DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
43612  DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
43613 }
43614 #endif /* DUK_USE_FINALIZER_SUPPORT */
43615 
43616 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
43617  DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
43618 
43619 #if defined(DUK_USE_DEBUG)
43620  duk_heap_dump_strtab(heap);
43621 #endif
43622 
43623 #if defined(DUK_USE_DEBUGGER_SUPPORT)
43624  /* Detach a debugger if attached (can be called multiple times)
43625  * safely.
43626  */
43627  /* XXX: Add a flag to reject an attempt to re-attach? Otherwise
43628  * the detached callback may immediately reattach.
43629  */
43630  duk_debug_do_detach(heap);
43631 #endif
43632 
43633  /* Execute finalizers before freeing the heap, even for reachable
43634  * objects, and regardless of whether or not mark-and-sweep is
43635  * enabled. This gives finalizers the chance to free any native
43636  * resources like file handles, allocations made outside Duktape,
43637  * etc. This is quite tricky to get right, so that all finalizer
43638  * guarantees are honored.
43639  *
43640  * XXX: this perhaps requires an execution time limit.
43641  */
43642  DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
43643  /* Run mark-and-sweep a few times just in case (unreachable object
43644  * finalizers run already here). The last round must rescue objects
43645  * from the previous round without running any more finalizers. This
43646  * ensures rescued objects get their FINALIZED flag cleared so that
43647  * their finalizer is called once more in forced finalization to
43648  * satisfy finalizer guarantees. However, we don't want to run any
43649  * more finalizer because that'd required one more loop, and so on.
43650  */
43651  DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
43652  duk_heap_mark_and_sweep(heap, 0);
43653  DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
43654  duk_heap_mark_and_sweep(heap, 0);
43655  DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
43656  duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_SKIP_FINALIZERS); /* skip finalizers; queue finalizable objects to heap_allocated */
43657 
43658 #if defined(DUK_USE_FINALIZER_SUPPORT)
43659  DUK_HEAP_SET_FINALIZER_NORESCUE(heap); /* rescue no longer supported */
43660  duk__free_run_finalizers(heap);
43661 #endif /* DUK_USE_FINALIZER_SUPPORT */
43662 
43663  /* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
43664  * are on the heap allocated list.
43665  */
43666 
43667  DUK_D(DUK_DPRINT("freeing heap objects of heap: %p", (void *) heap));
43668  duk__free_allocated(heap);
43669 
43670 #if defined(DUK_USE_REFERENCE_COUNTING)
43671  DUK_D(DUK_DPRINT("freeing refzero list of heap: %p", (void *) heap));
43672  duk__free_refzero_list(heap);
43673 #endif
43674 
43675  DUK_D(DUK_DPRINT("freeing mark-and-sweep finalize list of heap: %p", (void *) heap));
43676  duk__free_markandsweep_finalize_list(heap);
43677 
43678  DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
43679  duk__free_stringtable(heap);
43680 
43681  DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
43682  heap->free_func(heap->heap_udata, heap);
43683 }
43684 
43685 /*
43686  * Allocate a heap.
43687  *
43688  * String table is initialized with built-in strings from genbuiltins.py,
43689  * either by dynamically creating the strings or by referring to ROM strings.
43690  */
43691 
43692 #if defined(DUK_USE_ROM_STRINGS)
43693 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
43694 #if defined(DUK_USE_ASSERTIONS)
43695  duk_small_uint_t i;
43696 #endif
43697 
43698  /* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
43699  * so nothing to initialize for strs[].
43700  */
43701 
43702 #if defined(DUK_USE_ASSERTIONS)
43703  for (i = 0; i < sizeof(duk_rom_strings) / sizeof(const duk_hstring *); i++) {
43704  duk_uint32_t hash;
43705  const duk_hstring *h;
43706  h = duk_rom_strings[i];
43707  DUK_ASSERT(h != NULL);
43708  hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
43709  DUK_DD(DUK_DDPRINT("duk_rom_strings[%d] -> hash 0x%08lx, computed 0x%08lx",
43710  (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
43711  DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
43712  }
43713 #endif
43714  return 1;
43715 }
43716 #else /* DUK_USE_ROM_STRINGS */
43717 
43718 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
43719  duk_bitdecoder_ctx bd_ctx;
43720  duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
43721  duk_small_uint_t i;
43722 
43723  DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
43724  bd->data = (const duk_uint8_t *) duk_strings_data;
43725  bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
43726 
43727  for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
43728  duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
43729  duk_small_uint_t len;
43730  duk_hstring *h;
43731 
43732  len = duk_bd_decode_bitpacked_string(bd, tmp);
43733 
43734  /* No need to length check string: it will never exceed even
43735  * the 16-bit length maximum.
43736  */
43737  DUK_ASSERT(len <= 0xffffUL);
43738  DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
43739  h = duk_heap_string_intern(heap, tmp, len);
43740  if (!h) {
43741  goto error;
43742  }
43743  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
43744 
43745  /* Special flags checks. Since these strings are always
43746  * reachable and a string cannot appear twice in the string
43747  * table, there's no need to check/set these flags elsewhere.
43748  * The 'internal' flag is set by string intern code.
43749  */
43750  if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
43751  DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
43752  }
43753  if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
43754  DUK_HSTRING_SET_RESERVED_WORD(h);
43755  if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
43756  DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
43757  }
43758  }
43759 
43760  DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
43761 
43762  /* XXX: The incref macro takes a thread pointer but doesn't
43763  * use it right now.
43764  */
43765  DUK_HSTRING_INCREF(_never_referenced_, h);
43766 
43767 #if defined(DUK_USE_HEAPPTR16)
43768  heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
43769 #else
43770  heap->strs[i] = h;
43771 #endif
43772  }
43773 
43774  return 1;
43775 
43776  error:
43777  return 0;
43778 }
43779 #endif /* DUK_USE_ROM_STRINGS */
43780 
43781 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
43782  duk_hthread *thr;
43783 
43784  DUK_DD(DUK_DDPRINT("heap init: alloc heap thread"));
43785  thr = duk_hthread_alloc(heap,
43786  DUK_HOBJECT_FLAG_EXTENSIBLE |
43787  DUK_HOBJECT_FLAG_THREAD |
43788  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
43789  if (!thr) {
43790  DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
43791  return 0;
43792  }
43793  thr->state = DUK_HTHREAD_STATE_INACTIVE;
43794 #if defined(DUK_USE_ROM_STRINGS)
43795  /* No strs[] pointer. */
43796 #else /* DUK_USE_ROM_STRINGS */
43797 #if defined(DUK_USE_HEAPPTR16)
43798  thr->strs16 = heap->strs16;
43799 #else
43800  thr->strs = heap->strs;
43801 #endif
43802 #endif /* DUK_USE_ROM_STRINGS */
43803 
43804  heap->heap_thread = thr;
43805  DUK_HTHREAD_INCREF(thr, thr); /* Note: first argument not really used */
43806 
43807  /* 'thr' is now reachable */
43808 
43809  if (!duk_hthread_init_stacks(heap, thr)) {
43810  return 0;
43811  }
43812 
43813  /* XXX: this may now fail, and is not handled correctly */
43814  duk_hthread_create_builtin_objects(thr);
43815 
43816  /* default prototype (Note: 'thr' must be reachable) */
43817  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
43818 
43819  return 1;
43820 }
43821 
43822 #if defined(DUK_USE_DEBUG)
43823 #define DUK__DUMPSZ(t) do { \
43824  DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
43825  } while (0)
43826 
43827 /* These is not 100% because format would need to be non-portable "long long".
43828  * Also print out as doubles to catch cases where the "long" type is not wide
43829  * enough; the limits will then not be printed accurately but the magnitude
43830  * will be correct.
43831  */
43832 #define DUK__DUMPLM_SIGNED_RAW(t,a,b) do { \
43833  DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
43834  (long) (a), (long) (b), \
43835  (double) (a), (double) (b))); \
43836  } while (0)
43837 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b) do { \
43838  DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
43839  (unsigned long) (a), (unsigned long) (b), \
43840  (double) (a), (double) (b))); \
43841  } while (0)
43842 #define DUK__DUMPLM_SIGNED(t) do { \
43843  DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
43844  } while (0)
43845 #define DUK__DUMPLM_UNSIGNED(t) do { \
43846  DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
43847  } while (0)
43848 
43849 DUK_LOCAL void duk__dump_type_sizes(void) {
43850  DUK_D(DUK_DPRINT("sizeof()"));
43851 
43852  /* basic platform types */
43853  DUK__DUMPSZ(char);
43854  DUK__DUMPSZ(short);
43855  DUK__DUMPSZ(int);
43856  DUK__DUMPSZ(long);
43857  DUK__DUMPSZ(double);
43858  DUK__DUMPSZ(void *);
43859  DUK__DUMPSZ(size_t);
43860 
43861  /* basic types from duk_features.h */
43862  DUK__DUMPSZ(duk_uint8_t);
43863  DUK__DUMPSZ(duk_int8_t);
43864  DUK__DUMPSZ(duk_uint16_t);
43865  DUK__DUMPSZ(duk_int16_t);
43866  DUK__DUMPSZ(duk_uint32_t);
43867  DUK__DUMPSZ(duk_int32_t);
43868  DUK__DUMPSZ(duk_uint64_t);
43869  DUK__DUMPSZ(duk_int64_t);
43870  DUK__DUMPSZ(duk_uint_least8_t);
43871  DUK__DUMPSZ(duk_int_least8_t);
43872  DUK__DUMPSZ(duk_uint_least16_t);
43873  DUK__DUMPSZ(duk_int_least16_t);
43874  DUK__DUMPSZ(duk_uint_least32_t);
43875  DUK__DUMPSZ(duk_int_least32_t);
43876 #if defined(DUK_USE_64BIT_OPS)
43877  DUK__DUMPSZ(duk_uint_least64_t);
43878  DUK__DUMPSZ(duk_int_least64_t);
43879 #endif
43880  DUK__DUMPSZ(duk_uint_fast8_t);
43881  DUK__DUMPSZ(duk_int_fast8_t);
43882  DUK__DUMPSZ(duk_uint_fast16_t);
43883  DUK__DUMPSZ(duk_int_fast16_t);
43884  DUK__DUMPSZ(duk_uint_fast32_t);
43885  DUK__DUMPSZ(duk_int_fast32_t);
43886 #if defined(DUK_USE_64BIT_OPS)
43887  DUK__DUMPSZ(duk_uint_fast64_t);
43888  DUK__DUMPSZ(duk_int_fast64_t);
43889 #endif
43890  DUK__DUMPSZ(duk_uintptr_t);
43891  DUK__DUMPSZ(duk_intptr_t);
43892  DUK__DUMPSZ(duk_uintmax_t);
43893  DUK__DUMPSZ(duk_intmax_t);
43894  DUK__DUMPSZ(duk_double_t);
43895 
43896  /* important chosen base types */
43897  DUK__DUMPSZ(duk_int_t);
43898  DUK__DUMPSZ(duk_uint_t);
43899  DUK__DUMPSZ(duk_int_fast_t);
43900  DUK__DUMPSZ(duk_uint_fast_t);
43901  DUK__DUMPSZ(duk_small_int_t);
43902  DUK__DUMPSZ(duk_small_uint_t);
43903  DUK__DUMPSZ(duk_small_int_fast_t);
43904  DUK__DUMPSZ(duk_small_uint_fast_t);
43905 
43906  /* some derived types */
43907  DUK__DUMPSZ(duk_codepoint_t);
43908  DUK__DUMPSZ(duk_ucodepoint_t);
43909  DUK__DUMPSZ(duk_idx_t);
43910  DUK__DUMPSZ(duk_errcode_t);
43911  DUK__DUMPSZ(duk_uarridx_t);
43912 
43913  /* tval */
43914  DUK__DUMPSZ(duk_double_union);
43915  DUK__DUMPSZ(duk_tval);
43916 
43917  /* structs from duk_forwdecl.h */
43918  DUK__DUMPSZ(duk_jmpbuf); /* just one 'int' for C++ exceptions */
43919  DUK__DUMPSZ(duk_heaphdr);
43920  DUK__DUMPSZ(duk_heaphdr_string);
43921  DUK__DUMPSZ(duk_hstring);
43922  DUK__DUMPSZ(duk_hstring_external);
43923  DUK__DUMPSZ(duk_hobject);
43924  DUK__DUMPSZ(duk_harray);
43925  DUK__DUMPSZ(duk_hcompfunc);
43926  DUK__DUMPSZ(duk_hnatfunc);
43927  DUK__DUMPSZ(duk_hthread);
43928 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
43929  DUK__DUMPSZ(duk_hbufobj);
43930 #endif
43931  DUK__DUMPSZ(duk_hbuffer);
43932  DUK__DUMPSZ(duk_hbuffer_fixed);
43933  DUK__DUMPSZ(duk_hbuffer_dynamic);
43934  DUK__DUMPSZ(duk_hbuffer_external);
43935  DUK__DUMPSZ(duk_propaccessor);
43936  DUK__DUMPSZ(duk_propvalue);
43937  DUK__DUMPSZ(duk_propdesc);
43938  DUK__DUMPSZ(duk_heap);
43939 #if defined(DUK_USE_STRTAB_CHAIN)
43940  DUK__DUMPSZ(duk_strtab_entry);
43941 #endif
43942  DUK__DUMPSZ(duk_activation);
43943  DUK__DUMPSZ(duk_catcher);
43944  DUK__DUMPSZ(duk_strcache);
43945  DUK__DUMPSZ(duk_ljstate);
43946  DUK__DUMPSZ(duk_fixedbuffer);
43947  DUK__DUMPSZ(duk_bitdecoder_ctx);
43948  DUK__DUMPSZ(duk_bitencoder_ctx);
43949  DUK__DUMPSZ(duk_token);
43950  DUK__DUMPSZ(duk_re_token);
43951  DUK__DUMPSZ(duk_lexer_point);
43952  DUK__DUMPSZ(duk_lexer_ctx);
43953  DUK__DUMPSZ(duk_compiler_instr);
43954  DUK__DUMPSZ(duk_compiler_func);
43955  DUK__DUMPSZ(duk_compiler_ctx);
43956  DUK__DUMPSZ(duk_re_matcher_ctx);
43957  DUK__DUMPSZ(duk_re_compiler_ctx);
43958 }
43959 DUK_LOCAL void duk__dump_type_limits(void) {
43960  DUK_D(DUK_DPRINT("limits"));
43961 
43962  /* basic types */
43963  DUK__DUMPLM_SIGNED(INT8);
43964  DUK__DUMPLM_UNSIGNED(UINT8);
43965  DUK__DUMPLM_SIGNED(INT_FAST8);
43966  DUK__DUMPLM_UNSIGNED(UINT_FAST8);
43967  DUK__DUMPLM_SIGNED(INT_LEAST8);
43968  DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
43969  DUK__DUMPLM_SIGNED(INT16);
43970  DUK__DUMPLM_UNSIGNED(UINT16);
43971  DUK__DUMPLM_SIGNED(INT_FAST16);
43972  DUK__DUMPLM_UNSIGNED(UINT_FAST16);
43973  DUK__DUMPLM_SIGNED(INT_LEAST16);
43974  DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
43975  DUK__DUMPLM_SIGNED(INT32);
43976  DUK__DUMPLM_UNSIGNED(UINT32);
43977  DUK__DUMPLM_SIGNED(INT_FAST32);
43978  DUK__DUMPLM_UNSIGNED(UINT_FAST32);
43979  DUK__DUMPLM_SIGNED(INT_LEAST32);
43980  DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
43981 #if defined(DUK_USE_64BIT_OPS)
43982  DUK__DUMPLM_SIGNED(INT64);
43983  DUK__DUMPLM_UNSIGNED(UINT64);
43984  DUK__DUMPLM_SIGNED(INT_FAST64);
43985  DUK__DUMPLM_UNSIGNED(UINT_FAST64);
43986  DUK__DUMPLM_SIGNED(INT_LEAST64);
43987  DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
43988 #endif
43989  DUK__DUMPLM_SIGNED(INTPTR);
43990  DUK__DUMPLM_UNSIGNED(UINTPTR);
43991  DUK__DUMPLM_SIGNED(INTMAX);
43992  DUK__DUMPLM_UNSIGNED(UINTMAX);
43993 
43994  /* derived types */
43995  DUK__DUMPLM_SIGNED(INT);
43996  DUK__DUMPLM_UNSIGNED(UINT);
43997  DUK__DUMPLM_SIGNED(INT_FAST);
43998  DUK__DUMPLM_UNSIGNED(UINT_FAST);
43999  DUK__DUMPLM_SIGNED(SMALL_INT);
44000  DUK__DUMPLM_UNSIGNED(SMALL_UINT);
44001  DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
44002  DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
44003 }
44004 
44005 DUK_LOCAL void duk__dump_misc_options(void) {
44006  DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
44007  DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
44008  DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
44009  DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
44010  DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
44011  DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
44012 #if defined(DUK_USE_PACKED_TVAL)
44013  DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
44014 #else
44015  DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
44016 #endif
44017 #if defined(DUK_USE_VARIADIC_MACROS)
44018  DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
44019 #else
44020  DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
44021 #endif
44022 #if defined(DUK_USE_INTEGER_LE)
44023  DUK_D(DUK_DPRINT("integer endianness: little"));
44024 #elif defined(DUK_USE_INTEGER_ME)
44025  DUK_D(DUK_DPRINT("integer endianness: mixed"));
44026 #elif defined(DUK_USE_INTEGER_BE)
44027  DUK_D(DUK_DPRINT("integer endianness: big"));
44028 #else
44029  DUK_D(DUK_DPRINT("integer endianness: ???"));
44030 #endif
44031 #if defined(DUK_USE_DOUBLE_LE)
44032  DUK_D(DUK_DPRINT("IEEE double endianness: little"));
44033 #elif defined(DUK_USE_DOUBLE_ME)
44034  DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
44035 #elif defined(DUK_USE_DOUBLE_BE)
44036  DUK_D(DUK_DPRINT("IEEE double endianness: big"));
44037 #else
44038  DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
44039 #endif
44040 }
44041 #endif /* DUK_USE_DEBUG */
44042 
44043 DUK_INTERNAL
44044 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
44045  duk_realloc_function realloc_func,
44046  duk_free_function free_func,
44047  void *heap_udata,
44048  duk_fatal_function fatal_func) {
44049  duk_heap *res = NULL;
44050 
44051  DUK_D(DUK_DPRINT("allocate heap"));
44052 
44053  /*
44054  * Debug dump type sizes
44055  */
44056 
44057 #if defined(DUK_USE_DEBUG)
44058  duk__dump_misc_options();
44059  duk__dump_type_sizes();
44060  duk__dump_type_limits();
44061 #endif
44062 
44063  /*
44064  * If selftests enabled, run them as early as possible.
44065  */
44066 
44067 #if defined(DUK_USE_SELF_TESTS)
44068  if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
44069  fatal_func(heap_udata, "self test(s) failed");
44070  }
44071 #endif
44072 
44073  /*
44074  * Important assert-like checks that should be enabled even
44075  * when assertions are otherwise not enabled.
44076  */
44077 
44078 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
44079  /* Can't check sizeof() using preprocessor so explicit check.
44080  * This will be optimized away in practice; unfortunately a
44081  * warning is generated on some compilers as a result.
44082  */
44083 #if defined(DUK_USE_PACKED_TVAL)
44084  if (sizeof(duk_tval) != 8) {
44085 #else
44086  if (sizeof(duk_tval) != 16) {
44087 #endif
44088  fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
44089  }
44090 #endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
44091 
44092  /*
44093  * Computed values (e.g. INFINITY)
44094  */
44095 
44096 #if defined(DUK_USE_COMPUTED_NAN)
44097  do {
44098  /* Workaround for some exotic platforms where NAN is missing
44099  * and the expression (0.0 / 0.0) does NOT result in a NaN.
44100  * Such platforms use the global 'duk_computed_nan' which must
44101  * be initialized at runtime. Use 'volatile' to ensure that
44102  * the compiler will actually do the computation and not try
44103  * to do constant folding which might result in the original
44104  * problem.
44105  */
44106  volatile double dbl1 = 0.0;
44107  volatile double dbl2 = 0.0;
44108  duk_computed_nan = dbl1 / dbl2;
44109  } while (0);
44110 #endif
44111 
44112 #if defined(DUK_USE_COMPUTED_INFINITY)
44113  do {
44114  /* Similar workaround for INFINITY. */
44115  volatile double dbl1 = 1.0;
44116  volatile double dbl2 = 0.0;
44117  duk_computed_infinity = dbl1 / dbl2;
44118  } while (0);
44119 #endif
44120 
44121  /*
44122  * Allocate heap struct
44123  *
44124  * Use a raw call, all macros expect the heap to be initialized
44125  */
44126 
44127  res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
44128  if (!res) {
44129  goto error;
44130  }
44131 
44132  /*
44133  * Zero the struct, and start initializing roughly in order
44134  */
44135 
44136  DUK_MEMZERO(res, sizeof(*res));
44137 
44138  /* explicit NULL inits */
44139 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44140  res->heap_udata = NULL;
44141  res->heap_allocated = NULL;
44142 #if defined(DUK_USE_REFERENCE_COUNTING)
44143  res->refzero_list = NULL;
44144  res->refzero_list_tail = NULL;
44145 #endif
44146  res->finalize_list = NULL;
44147  res->heap_thread = NULL;
44148  res->curr_thread = NULL;
44149  res->heap_object = NULL;
44150 #if defined(DUK_USE_STRTAB_CHAIN)
44151  /* nothing to NULL */
44152 #elif defined(DUK_USE_STRTAB_PROBE)
44153 #if defined(DUK_USE_HEAPPTR16)
44154  res->strtable16 = (duk_uint16_t *) NULL;
44155 #else
44156  res->strtable = (duk_hstring **) NULL;
44157 #endif
44158 #endif
44159 #if defined(DUK_USE_ROM_STRINGS)
44160  /* no res->strs[] */
44161 #else /* DUK_USE_ROM_STRINGS */
44162 #if defined(DUK_USE_HEAPPTR16)
44163  /* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
44164 #else
44165  {
44166  duk_small_uint_t i;
44167  for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
44168  res->strs[i] = NULL;
44169  }
44170  }
44171 #endif
44172 #endif /* DUK_USE_ROM_STRINGS */
44173 #if defined(DUK_USE_DEBUGGER_SUPPORT)
44174  res->dbg_read_cb = NULL;
44175  res->dbg_write_cb = NULL;
44176  res->dbg_peek_cb = NULL;
44177  res->dbg_read_flush_cb = NULL;
44178  res->dbg_write_flush_cb = NULL;
44179  res->dbg_request_cb = NULL;
44180  res->dbg_udata = NULL;
44181  res->dbg_step_thread = NULL;
44182 #endif
44183 #endif /* DUK_USE_EXPLICIT_NULL_INIT */
44184 
44185  res->alloc_func = alloc_func;
44186  res->realloc_func = realloc_func;
44187  res->free_func = free_func;
44188  res->heap_udata = heap_udata;
44189  res->fatal_func = fatal_func;
44190 
44191 #if defined(DUK_USE_HEAPPTR16)
44192  /* XXX: zero assumption */
44193  res->heapptr_null16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) NULL);
44194  res->heapptr_deleted16 = DUK_USE_HEAPPTR_ENC16(res->heap_udata, (void *) DUK_STRTAB_DELETED_MARKER(res));
44195 #endif
44196 
44197  /* res->mark_and_sweep_trigger_counter == 0 -> now causes immediate GC; which is OK */
44198 
44199  res->call_recursion_depth = 0;
44200  res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
44201 
44202  /* XXX: use the pointer as a seed for now: mix in time at least */
44203 
44204  /* The casts through duk_intptr_t is to avoid the following GCC warning:
44205  *
44206  * warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
44207  *
44208  * This still generates a /Wp64 warning on VS2010 when compiling for x86.
44209  */
44210 #if defined(DUK_USE_ROM_STRINGS)
44211  /* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
44212  DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
44213  res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
44214 #else /* DUK_USE_ROM_STRINGS */
44215  res->hash_seed = (duk_uint32_t) (duk_intptr_t) res;
44216 #if !defined(DUK_USE_STRHASH_DENSE)
44217  res->hash_seed ^= 5381; /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
44218 #endif
44219 #endif /* DUK_USE_ROM_STRINGS */
44220 
44221 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44222  res->lj.jmpbuf_ptr = NULL;
44223 #endif
44224  DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN); /* zero */
44225 
44226  DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
44227  DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
44228 
44229 #if (DUK_STRTAB_INITIAL_SIZE < DUK_UTIL_MIN_HASH_PRIME)
44230 #error initial heap stringtable size is defined incorrectly
44231 #endif
44232 
44233  /*
44234  * Init stringtable: fixed variant
44235  */
44236 
44237 #if defined(DUK_USE_STRTAB_CHAIN)
44238  DUK_MEMZERO(res->strtable, sizeof(duk_strtab_entry) * DUK_STRTAB_CHAIN_SIZE);
44239 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44240  {
44241  duk_small_uint_t i;
44242  for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
44243 #if defined(DUK_USE_HEAPPTR16)
44244  res->strtable[i].u.str16 = res->heapptr_null16;
44245 #else
44246  res->strtable[i].u.str = NULL;
44247 #endif
44248  }
44249  }
44250 #endif /* DUK_USE_EXPLICIT_NULL_INIT */
44251 #endif /* DUK_USE_STRTAB_CHAIN */
44252 
44253  /*
44254  * Init stringtable: probe variant
44255  */
44256 
44257 #if defined(DUK_USE_STRTAB_PROBE)
44258 #if defined(DUK_USE_HEAPPTR16)
44259  res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
44260  if (!res->strtable16) {
44261  goto error;
44262  }
44263 #else /* DUK_USE_HEAPPTR16 */
44264  res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
44265  if (!res->strtable) {
44266  goto error;
44267  }
44268 #endif /* DUK_USE_HEAPPTR16 */
44269  res->st_size = DUK_STRTAB_INITIAL_SIZE;
44270 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44271  {
44272  duk_small_uint_t i;
44273  DUK_ASSERT(res->st_size == DUK_STRTAB_INITIAL_SIZE);
44274  for (i = 0; i < DUK_STRTAB_INITIAL_SIZE; i++) {
44275 #if defined(DUK_USE_HEAPPTR16)
44276  res->strtable16[i] = res->heapptr_null16;
44277 #else
44278  res->strtable[i] = NULL;
44279 #endif
44280  }
44281  }
44282 #else /* DUK_USE_EXPLICIT_NULL_INIT */
44283 #if defined(DUK_USE_HEAPPTR16)
44284  DUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * DUK_STRTAB_INITIAL_SIZE);
44285 #else
44286  DUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * DUK_STRTAB_INITIAL_SIZE);
44287 #endif
44288 #endif /* DUK_USE_EXPLICIT_NULL_INIT */
44289 #endif /* DUK_USE_STRTAB_PROBE */
44290 
44291  /*
44292  * Init stringcache
44293  */
44294 
44295 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
44296  {
44297  duk_small_uint_t i;
44298  for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
44299  res->strcache[i].h = NULL;
44300  }
44301  }
44302 #endif
44303 
44304  /* XXX: error handling is incomplete. It would be cleanest if
44305  * there was a setjmp catchpoint, so that all init code could
44306  * freely throw errors. If that were the case, the return code
44307  * passing here could be removed.
44308  */
44309 
44310  /*
44311  * Init built-in strings
44312  */
44313 
44314  DUK_DD(DUK_DDPRINT("HEAP: INIT STRINGS"));
44315  if (!duk__init_heap_strings(res)) {
44316  goto error;
44317  }
44318 
44319  /*
44320  * Init the heap thread
44321  */
44322 
44323  DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP THREAD"));
44324  if (!duk__init_heap_thread(res)) {
44325  goto error;
44326  }
44327 
44328  /*
44329  * Init the heap object
44330  */
44331 
44332  DUK_DD(DUK_DDPRINT("HEAP: INIT HEAP OBJECT"));
44333  DUK_ASSERT(res->heap_thread != NULL);
44334  res->heap_object = duk_hobject_alloc(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
44335  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
44336  if (!res->heap_object) {
44337  goto error;
44338  }
44339  DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
44340 
44341  /*
44342  * Odds and ends depending on the heap thread
44343  */
44344 
44345 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
44346 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
44347  res->rnd_state = (duk_uint32_t) DUK_USE_DATE_GET_NOW((duk_context *) res->heap_thread);
44348  duk_util_tinyrandom_prepare_seed(res->heap_thread);
44349 #else
44350  res->rnd_state[0] = (duk_uint64_t) DUK_USE_DATE_GET_NOW((duk_context *) res->heap_thread);
44351  DUK_ASSERT(res->rnd_state[1] == 0); /* Not filled here, filled in by seed preparation. */
44352 #if 0 /* Manual test values matching misc/xoroshiro128plus_test.c. */
44353  res->rnd_state[0] = 0xdeadbeef12345678ULL;
44354  res->rnd_state[1] = 0xcafed00d12345678ULL;
44355 #endif
44356  duk_util_tinyrandom_prepare_seed(res->heap_thread);
44357  /* Mix in heap pointer: this ensures that if two Duktape heaps are
44358  * created on the same millisecond, they get a different PRNG
44359  * sequence (unless e.g. virtual memory addresses cause also the
44360  * heap object pointer to be the same).
44361  */
44362  {
44363  duk_uint64_t tmp_u64;
44364  tmp_u64 = 0;
44365  DUK_MEMCPY((void *) &tmp_u64,
44366  (const void *) &res,
44367  (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
44368  res->rnd_state[1] ^= tmp_u64;
44369  }
44370  do {
44371  duk_small_uint_t i;
44372  for (i = 0; i < 10; i++) {
44373  /* Throw away a few initial random numbers just in
44374  * case. Probably unnecessary due to SplitMix64
44375  * preparation.
44376  */
44377  (void) duk_util_tinyrandom_get_double(res->heap_thread);
44378  }
44379  } while (0);
44380 #endif
44381 #endif
44382 
44383  /*
44384  * All done
44385  */
44386 
44387  DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
44388  return res;
44389 
44390  error:
44391  DUK_D(DUK_DPRINT("heap allocation failed"));
44392 
44393  if (res) {
44394  /* assumes that allocated pointers and alloc funcs are valid
44395  * if res exists
44396  */
44397  DUK_ASSERT(res->alloc_func != NULL);
44398  DUK_ASSERT(res->realloc_func != NULL);
44399  DUK_ASSERT(res->free_func != NULL);
44400  duk_heap_free(res);
44401  }
44402  return NULL;
44403 }
44404 
44405 /* automatic undefs */
44406 #undef DUK__DUMPLM_SIGNED
44407 #undef DUK__DUMPLM_SIGNED_RAW
44408 #undef DUK__DUMPLM_UNSIGNED
44409 #undef DUK__DUMPLM_UNSIGNED_RAW
44410 #undef DUK__DUMPSZ
44411 #undef DUK__FIXED_HASH_SEED
44412 /*
44413  * String hash computation (interning).
44414  *
44415  * String hashing is performance critical because a string hash is computed
44416  * for all new strings which are candidates to be added to the string table.
44417  * However, strings actually added to the string table go through a codepoint
44418  * length calculation which dominates performance because it goes through
44419  * every byte of the input string (but only for strings added).
44420  *
44421  * The string hash algorithm should be fast, but on the other hand provide
44422  * good enough hashes to ensure both string table and object property table
44423  * hash tables work reasonably well (i.e., there aren't too many collisions
44424  * with real world inputs). Unless the hash is cryptographic, it's always
44425  * possible to craft inputs with maximal hash collisions.
44426  *
44427  * NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
44428  * for ROM string support!
44429  */
44430 
44431 /* #include duk_internal.h -> already included */
44432 
44433 #if defined(DUK_USE_STRHASH_DENSE)
44434 /* Constants for duk_hashstring(). */
44435 #define DUK__STRHASH_SHORTSTRING 4096L
44436 #define DUK__STRHASH_MEDIUMSTRING (256L * 1024L)
44437 #define DUK__STRHASH_BLOCKSIZE 256L
44438 
44439 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
44440  duk_uint32_t hash;
44441 
44442  /* Use Murmurhash2 directly for short strings, and use "block skipping"
44443  * for long strings: hash an initial part and then sample the rest of
44444  * the string with reasonably sized chunks. An initial offset for the
44445  * sampling is computed based on a hash of the initial part of the string;
44446  * this is done to (usually) avoid the case where all long strings have
44447  * certain offset ranges which are never sampled.
44448  *
44449  * Skip should depend on length and bound the total time to roughly
44450  * logarithmic. With current values:
44451  *
44452  * 1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
44453  * 1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
44454  *
44455  * XXX: It would be better to compute the skip offset more "smoothly"
44456  * instead of having a few boundary values.
44457  */
44458 
44459  /* note: mixing len into seed improves hashing when skipping */
44460  duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
44461 
44462  if (len <= DUK__STRHASH_SHORTSTRING) {
44463  hash = duk_util_hashbytes(str, len, str_seed);
44464  } else {
44465  duk_size_t off;
44466  duk_size_t skip;
44467 
44468  if (len <= DUK__STRHASH_MEDIUMSTRING) {
44469  skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
44470  } else {
44471  skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
44472  }
44473 
44474  hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
44475  off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
44476 
44477  /* XXX: inefficient loop */
44478  while (off < len) {
44479  duk_size_t left = len - off;
44480  duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
44481  hash ^= duk_util_hashbytes(str + off, now, str_seed);
44482  off += skip;
44483  }
44484  }
44485 
44486 #if defined(DUK_USE_STRHASH16)
44487  /* Truncate to 16 bits here, so that a computed hash can be compared
44488  * against a hash stored in a 16-bit field.
44489  */
44490  hash &= 0x0000ffffUL;
44491 #endif
44492  return hash;
44493 }
44494 #else /* DUK_USE_STRHASH_DENSE */
44495 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
44496  duk_uint32_t hash;
44497  duk_size_t step;
44498  duk_size_t off;
44499 
44500  /* Slightly modified "Bernstein hash" from:
44501  *
44502  * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
44503  *
44504  * Modifications: string skipping and reverse direction similar to
44505  * Lua 5.1.5, and different hash initializer.
44506  *
44507  * The reverse direction ensures last byte it always included in the
44508  * hash which is a good default as changing parts of the string are
44509  * more often in the suffix than in the prefix.
44510  */
44511 
44512  hash = heap->hash_seed ^ ((duk_uint32_t) len); /* Bernstein hash init value is normally 5381 */
44513  step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
44514  for (off = len; off >= step; off -= step) {
44515  DUK_ASSERT(off >= 1); /* off >= step, and step >= 1 */
44516  hash = (hash * 33) + str[off - 1];
44517  }
44518 
44519 #if defined(DUK_USE_STRHASH16)
44520  /* Truncate to 16 bits here, so that a computed hash can be compared
44521  * against a hash stored in a 16-bit field.
44522  */
44523  hash &= 0x0000ffffUL;
44524 #endif
44525  return hash;
44526 }
44527 #endif /* DUK_USE_STRHASH_DENSE */
44528 
44529 /* automatic undefs */
44530 #undef DUK__STRHASH_BLOCKSIZE
44531 #undef DUK__STRHASH_MEDIUMSTRING
44532 #undef DUK__STRHASH_SHORTSTRING
44533 /*
44534  * Mark-and-sweep garbage collection.
44535  */
44536 
44537 /* #include duk_internal.h -> already included */
44538 
44539 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
44540 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
44541 
44542 /*
44543  * Misc
44544  */
44545 
44546 /* Select a thread for mark-and-sweep use.
44547  *
44548  * XXX: This needs to change later.
44549  */
44550 DUK_LOCAL duk_hthread *duk__get_temp_hthread(duk_heap *heap) {
44551  if (heap->curr_thread) {
44552  return heap->curr_thread;
44553  }
44554  return heap->heap_thread; /* may be NULL, too */
44555 }
44556 
44557 /*
44558  * Marking functions for heap types: mark children recursively
44559  */
44560 
44561 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
44562  DUK_UNREF(heap);
44563  DUK_UNREF(h);
44564 
44565  DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
44566  DUK_ASSERT(h);
44567 
44568  /* nothing to process */
44569 }
44570 
44571 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
44572  duk_uint_fast32_t i;
44573 
44574  DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
44575 
44576  DUK_ASSERT(h);
44577 
44578  /* XXX: use advancing pointers instead of index macros -> faster and smaller? */
44579 
44580  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
44581  duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
44582  if (!key) {
44583  continue;
44584  }
44585  duk__mark_heaphdr(heap, (duk_heaphdr *) key);
44586  if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
44587  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
44588  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
44589  } else {
44590  duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
44591  }
44592  }
44593 
44594  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
44595  duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
44596  }
44597 
44598  /* hash part is a 'weak reference' and does not contribute */
44599 
44600  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
44601 
44602  /* XXX: rearrange bits to allow a switch case to be used here? */
44603  /* XXX: add a fast path for objects (and arrays)? */
44604  /* DUK_HOBJECT_IS_ARRAY(h): needs no special handling now as there are
44605  * no extra fields in need of marking.
44606  */
44607  if (DUK_HOBJECT_IS_COMPFUNC(h)) {
44608  duk_hcompfunc *f = (duk_hcompfunc *) h;
44609  duk_tval *tv, *tv_end;
44610  duk_hobject **fn, **fn_end;
44611 
44612  /* 'data' is reachable through every compiled function which
44613  * contains a reference.
44614  */
44615 
44616  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
44617  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
44618  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
44619 
44620  if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
44621  tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
44622  tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
44623  while (tv < tv_end) {
44624  duk__mark_tval(heap, tv);
44625  tv++;
44626  }
44627 
44628  fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
44629  fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
44630  while (fn < fn_end) {
44631  duk__mark_heaphdr(heap, (duk_heaphdr *) *fn);
44632  fn++;
44633  }
44634  } else {
44635  /* May happen in some out-of-memory corner cases. */
44636  DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
44637  }
44638  } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
44639  duk_hnatfunc *f = (duk_hnatfunc *) h;
44640  DUK_UNREF(f);
44641  /* nothing to mark */
44642 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
44643  } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
44644  duk_hbufobj *b = (duk_hbufobj *) h;
44645  duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
44646  duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
44647 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
44648  } else if (DUK_HOBJECT_IS_THREAD(h)) {
44649  duk_hthread *t = (duk_hthread *) h;
44650  duk_tval *tv;
44651 
44652  tv = t->valstack;
44653  while (tv < t->valstack_top) {
44654  duk__mark_tval(heap, tv);
44655  tv++;
44656  }
44657 
44658  for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
44659  duk_activation *act = t->callstack + i;
44660  duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
44661  duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
44662  duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
44663 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
44664  duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
44665 #endif
44666  }
44667 
44668 #if 0 /* nothing now */
44669  for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
44670  duk_catcher *cat = t->catchstack + i;
44671  }
44672 #endif
44673 
44674  duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
44675 
44676  /* XXX: duk_small_uint_t would be enough for this loop */
44677  for (i = 0; i < DUK_NUM_BUILTINS; i++) {
44678  duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
44679  }
44680  }
44681 }
44682 
44683 /* recursion tracking happens here only */
44684 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
44685  DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
44686  (void *) h,
44687  (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
44688  if (!h) {
44689  return;
44690  }
44691 #if defined(DUK_USE_ROM_OBJECTS)
44692  if (DUK_HEAPHDR_HAS_READONLY(h)) {
44693  DUK_DDD(DUK_DDDPRINT("readonly object %p, skip", (void *) h));
44694  return;
44695  }
44696 #endif
44697  if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
44698  DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
44699  return;
44700  }
44701  DUK_HEAPHDR_SET_REACHABLE(h);
44702 
44703  if (heap->mark_and_sweep_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
44704  /* log this with a normal debug level because this should be relatively rare */
44705  DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
44706  DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
44707  DUK_HEAPHDR_SET_TEMPROOT(h);
44708  return;
44709  }
44710 
44711  heap->mark_and_sweep_recursion_depth++;
44712 
44713  switch (DUK_HEAPHDR_GET_TYPE(h)) {
44714  case DUK_HTYPE_STRING:
44715  duk__mark_hstring(heap, (duk_hstring *) h);
44716  break;
44717  case DUK_HTYPE_OBJECT:
44718  duk__mark_hobject(heap, (duk_hobject *) h);
44719  break;
44720  case DUK_HTYPE_BUFFER:
44721  /* nothing to mark */
44722  break;
44723  default:
44724  DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
44725  DUK_UNREACHABLE();
44726  }
44727 
44728  heap->mark_and_sweep_recursion_depth--;
44729 }
44730 
44731 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
44732  DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
44733  if (!tv) {
44734  return;
44735  }
44736  if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
44737  duk__mark_heaphdr(heap, DUK_TVAL_GET_HEAPHDR(tv));
44738  }
44739 }
44740 
44741 /*
44742  * Mark the heap.
44743  */
44744 
44745 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
44746  duk_small_uint_t i;
44747 
44748  DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
44749 
44750  duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
44751  duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
44752 
44753  for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
44754  duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
44755  duk__mark_heaphdr(heap, (duk_heaphdr *) h);
44756  }
44757 
44758  duk__mark_tval(heap, &heap->lj.value1);
44759  duk__mark_tval(heap, &heap->lj.value2);
44760 
44761 #if defined(DUK_USE_DEBUGGER_SUPPORT)
44762  for (i = 0; i < heap->dbg_breakpoint_count; i++) {
44763  duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
44764  }
44765 #endif
44766 }
44767 
44768 /*
44769  * Mark refzero_list objects.
44770  *
44771  * Objects on the refzero_list have no inbound references. They might have
44772  * outbound references to objects that we might free, which would invalidate
44773  * any references held by the refzero objects. A refzero object might also
44774  * be rescued by refcount finalization. Refzero objects are treated as
44775  * reachability roots to ensure they (or anything they point to) are not
44776  * freed in mark-and-sweep.
44777  */
44778 
44779 #if defined(DUK_USE_REFERENCE_COUNTING)
44780 DUK_LOCAL void duk__mark_refzero_list(duk_heap *heap) {
44781  duk_heaphdr *hdr;
44782 
44783  DUK_DD(DUK_DDPRINT("duk__mark_refzero_list: %p", (void *) heap));
44784 
44785  hdr = heap->refzero_list;
44786  while (hdr) {
44787  duk__mark_heaphdr(heap, hdr);
44788  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44789  }
44790 }
44791 #endif
44792 
44793 /*
44794  * Mark unreachable, finalizable objects.
44795  *
44796  * Such objects will be moved aside and their finalizers run later. They have
44797  * to be treated as reachability roots for their properties etc to remain
44798  * allocated. This marking is only done for unreachable values which would
44799  * be swept later (refzero_list is thus excluded).
44800  *
44801  * Objects are first marked FINALIZABLE and only then marked as reachability
44802  * roots; otherwise circular references might be handled inconsistently.
44803  */
44804 
44805 #if defined(DUK_USE_FINALIZER_SUPPORT)
44806 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
44807  duk_hthread *thr;
44808  duk_heaphdr *hdr;
44809  duk_size_t count_finalizable = 0;
44810 
44811  DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
44812 
44813  thr = duk__get_temp_hthread(heap);
44814  DUK_ASSERT(thr != NULL);
44815 
44816  hdr = heap->heap_allocated;
44817  while (hdr) {
44818  /* A finalizer is looked up from the object and up its prototype chain
44819  * (which allows inherited finalizers). A prototype loop must not cause
44820  * an error to be thrown here; duk_hobject_hasprop_raw() will ignore a
44821  * prototype loop silently and indicate that the property doesn't exist.
44822  */
44823 
44824  if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
44825  DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_OBJECT &&
44826  !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
44827  duk_hobject_hasprop_raw(thr, (duk_hobject *) hdr, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
44828 
44829  /* heaphdr:
44830  * - is not reachable
44831  * - is an object
44832  * - is not a finalized object
44833  * - has a finalizer
44834  */
44835 
44836  DUK_DD(DUK_DDPRINT("unreachable heap object will be "
44837  "finalized -> mark as finalizable "
44838  "and treat as a reachability root: %p",
44839  (void *) hdr));
44840  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
44841  DUK_HEAPHDR_SET_FINALIZABLE(hdr);
44842  count_finalizable ++;
44843  }
44844 
44845  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44846  }
44847 
44848  if (count_finalizable == 0) {
44849  return;
44850  }
44851 
44852  DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
44853  (long) count_finalizable));
44854 
44855  hdr = heap->heap_allocated;
44856  while (hdr) {
44857  if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
44858  duk__mark_heaphdr(heap, hdr);
44859  }
44860 
44861  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44862  }
44863 
44864  /* Caller will finish the marking process if we hit a recursion limit. */
44865 }
44866 #endif /* DUK_USE_FINALIZER_SUPPORT */
44867 
44868 /*
44869  * Mark objects on finalize_list.
44870  *
44871  */
44872 
44873 #if defined(DUK_USE_FINALIZER_SUPPORT)
44874 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
44875  duk_heaphdr *hdr;
44876 #if defined(DUK_USE_DEBUG)
44877  duk_size_t count_finalize_list = 0;
44878 #endif
44879 
44880  DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
44881 
44882  hdr = heap->finalize_list;
44883  while (hdr) {
44884  duk__mark_heaphdr(heap, hdr);
44885  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44886 #if defined(DUK_USE_DEBUG)
44887  count_finalize_list++;
44888 #endif
44889  }
44890 
44891 #if defined(DUK_USE_DEBUG)
44892  if (count_finalize_list > 0) {
44893  DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
44894  (long) count_finalize_list));
44895  }
44896 #endif
44897 }
44898 #endif /* DUK_USE_FINALIZER_SUPPORT */
44899 
44900 /*
44901  * Fallback marking handler if recursion limit is reached.
44902  *
44903  * Iterates 'temproots' until recursion limit is no longer hit. Note
44904  * that temproots may reside either in heap allocated list or the
44905  * refzero work list. This is a slow scan, but guarantees that we
44906  * finish with a bounded C stack.
44907  *
44908  * Note that nodes may have been marked as temproots before this
44909  * scan begun, OR they may have been marked during the scan (as
44910  * we process nodes recursively also during the scan). This is
44911  * intended behavior.
44912  */
44913 
44914 #if defined(DUK_USE_DEBUG)
44915 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
44916 #else
44917 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
44918 #endif
44919  if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
44920  DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
44921  return;
44922  }
44923 
44924  DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
44925  DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
44926  DUK_HEAPHDR_CLEAR_REACHABLE(hdr); /* done so that duk__mark_heaphdr() works correctly */
44927  duk__mark_heaphdr(heap, hdr);
44928 
44929 #if defined(DUK_USE_DEBUG)
44930  (*count)++;
44931 #endif
44932 }
44933 
44934 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
44935  duk_heaphdr *hdr;
44936 #if defined(DUK_USE_DEBUG)
44937  duk_size_t count;
44938 #endif
44939 
44940  DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
44941 
44942  while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
44943  DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
44944 
44945 #if defined(DUK_USE_DEBUG)
44946  count = 0;
44947 #endif
44948  DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
44949 
44950  hdr = heap->heap_allocated;
44951  while (hdr) {
44952 #if defined(DUK_USE_DEBUG)
44953  duk__handle_temproot(heap, hdr, &count);
44954 #else
44955  duk__handle_temproot(heap, hdr);
44956 #endif
44957  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44958  }
44959 
44960  /* must also check refzero_list */
44961 #if defined(DUK_USE_REFERENCE_COUNTING)
44962  hdr = heap->refzero_list;
44963  while (hdr) {
44964 #if defined(DUK_USE_DEBUG)
44965  duk__handle_temproot(heap, hdr, &count);
44966 #else
44967  duk__handle_temproot(heap, hdr);
44968 #endif
44969  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44970  }
44971 #endif /* DUK_USE_REFERENCE_COUNTING */
44972 
44973 #if defined(DUK_USE_DEBUG)
44974  DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
44975 #endif
44976  }
44977 }
44978 
44979 /*
44980  * Finalize refcounts for heap elements just about to be freed.
44981  * This must be done for all objects before freeing to avoid any
44982  * stale pointer dereferences.
44983  *
44984  * Note that this must deduce the set of objects to be freed
44985  * identically to duk__sweep_heap().
44986  */
44987 
44988 #if defined(DUK_USE_REFERENCE_COUNTING)
44989 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
44990  duk_hthread *thr;
44991  duk_heaphdr *hdr;
44992 
44993  thr = duk__get_temp_hthread(heap);
44994  DUK_ASSERT(thr != NULL);
44995 
44996  DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p, hthread=%p",
44997  (void *) heap, (void *) thr));
44998 
44999  hdr = heap->heap_allocated;
45000  while (hdr) {
45001  if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
45002  /*
45003  * Unreachable object about to be swept. Finalize target refcounts
45004  * (objects which the unreachable object points to) without doing
45005  * refzero processing. Recursive decrefs are also prevented when
45006  * refzero processing is disabled.
45007  *
45008  * Value cannot be a finalizable object, as they have been made
45009  * temporarily reachable for this round.
45010  */
45011 
45012  DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
45013  duk_heaphdr_refcount_finalize(thr, hdr);
45014  }
45015 
45016  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45017  }
45018 }
45019 #endif /* DUK_USE_REFERENCE_COUNTING */
45020 
45021 /*
45022  * Clear (reachable) flags of refzero work list.
45023  */
45024 
45025 #if defined(DUK_USE_REFERENCE_COUNTING)
45026 DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
45027  duk_heaphdr *hdr;
45028 
45029  DUK_DD(DUK_DDPRINT("duk__clear_refzero_list_flags: %p", (void *) heap));
45030 
45031  hdr = heap->refzero_list;
45032  while (hdr) {
45033  DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
45034  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
45035  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
45036  DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
45037  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45038  }
45039 }
45040 #endif /* DUK_USE_REFERENCE_COUNTING */
45041 
45042 /*
45043  * Clear (reachable) flags of finalize_list
45044  *
45045  * We could mostly do in the sweep phase when we move objects from the
45046  * heap into the finalize_list. However, if a finalizer run is skipped
45047  * during a mark-and-sweep, the objects on the finalize_list will be marked
45048  * reachable during the next mark-and-sweep. Since they're already on the
45049  * finalize_list, no-one will be clearing their REACHABLE flag so we do it
45050  * here. (This now overlaps with the sweep handling in a harmless way.)
45051  */
45052 
45053 #if defined(DUK_USE_FINALIZER_SUPPORT)
45054 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
45055  duk_heaphdr *hdr;
45056 
45057  DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
45058 
45059  hdr = heap->finalize_list;
45060  while (hdr) {
45061  DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
45062  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
45063  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
45064  DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
45065  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45066  }
45067 }
45068 #endif /* DUK_USE_FINALIZER_SUPPORT */
45069 
45070 /*
45071  * Sweep stringtable
45072  */
45073 
45074 #if defined(DUK_USE_STRTAB_CHAIN)
45075 
45076 /* XXX: skip count_free w/o debug? */
45077 #if defined(DUK_USE_HEAPPTR16)
45078 DUK_LOCAL void duk__sweep_string_chain16(duk_heap *heap, duk_uint16_t *slot, duk_size_t *count_keep, duk_size_t *count_free) {
45079  duk_uint16_t h16 = *slot;
45080  duk_hstring *h;
45081  duk_uint16_t null16 = heap->heapptr_null16;
45082 
45083  if (h16 == null16) {
45084  /* nop */
45085  return;
45086  }
45087  h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, h16);
45088  DUK_ASSERT(h != NULL);
45089 
45090  if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
45091  DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
45092  (*count_keep)++;
45093  } else {
45094 #if defined(DUK_USE_REFERENCE_COUNTING)
45095  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
45096 #endif
45097  /* deal with weak references first */
45098  duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
45099  *slot = null16;
45100 
45101  /* free inner references (these exist e.g. when external
45102  * strings are enabled)
45103  */
45104  duk_free_hstring(heap, h);
45105  (*count_free)++;
45106  }
45107 }
45108 #else /* DUK_USE_HEAPPTR16 */
45109 DUK_LOCAL void duk__sweep_string_chain(duk_heap *heap, duk_hstring **slot, duk_size_t *count_keep, duk_size_t *count_free) {
45110  duk_hstring *h = *slot;
45111 
45112  if (h == NULL) {
45113  /* nop */
45114  return;
45115  }
45116 
45117  if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
45118  DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
45119  (*count_keep)++;
45120  } else {
45121 #if defined(DUK_USE_REFERENCE_COUNTING)
45122  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
45123 #endif
45124  /* deal with weak references first */
45125  duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
45126  *slot = NULL;
45127 
45128  /* free inner references (these exist e.g. when external
45129  * strings are enabled)
45130  */
45131  duk_free_hstring(heap, h);
45132  (*count_free)++;
45133  }
45134 }
45135 #endif /* DUK_USE_HEAPPTR16 */
45136 
45137 DUK_LOCAL void duk__sweep_stringtable_chain(duk_heap *heap, duk_size_t *out_count_keep) {
45138  duk_strtab_entry *e;
45139  duk_uint_fast32_t i;
45140  duk_size_t count_free = 0;
45141  duk_size_t count_keep = 0;
45142  duk_size_t j, n;
45143 #if defined(DUK_USE_HEAPPTR16)
45144  duk_uint16_t *lst;
45145 #else
45146  duk_hstring **lst;
45147 #endif
45148 
45149  DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
45150 
45151  /* Non-zero refcounts should not happen for unreachable strings,
45152  * because we refcount finalize all unreachable objects which
45153  * should have decreased unreachable string refcounts to zero
45154  * (even for cycles).
45155  */
45156 
45157  for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
45158  e = heap->strtable + i;
45159  if (e->listlen == 0) {
45160 #if defined(DUK_USE_HEAPPTR16)
45161  duk__sweep_string_chain16(heap, &e->u.str16, &count_keep, &count_free);
45162 #else
45163  duk__sweep_string_chain(heap, &e->u.str, &count_keep, &count_free);
45164 #endif
45165  } else {
45166 #if defined(DUK_USE_HEAPPTR16)
45167  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
45168 #else
45169  lst = e->u.strlist;
45170 #endif
45171  for (j = 0, n = e->listlen; j < n; j++) {
45172 #if defined(DUK_USE_HEAPPTR16)
45173  duk__sweep_string_chain16(heap, lst + j, &count_keep, &count_free);
45174 #else
45175  duk__sweep_string_chain(heap, lst + j, &count_keep, &count_free);
45176 #endif
45177  }
45178  }
45179  }
45180 
45181  DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
45182  (long) count_free, (long) count_keep));
45183  *out_count_keep = count_keep;
45184 }
45185 #endif /* DUK_USE_STRTAB_CHAIN */
45186 
45187 #if defined(DUK_USE_STRTAB_PROBE)
45188 DUK_LOCAL void duk__sweep_stringtable_probe(duk_heap *heap, duk_size_t *out_count_keep) {
45189  duk_hstring *h;
45190  duk_uint_fast32_t i;
45191 #if defined(DUK_USE_DEBUG)
45192  duk_size_t count_free = 0;
45193 #endif
45194  duk_size_t count_keep = 0;
45195 
45196  DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
45197 
45198  for (i = 0; i < heap->st_size; i++) {
45199 #if defined(DUK_USE_HEAPPTR16)
45200  h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
45201 #else
45202  h = heap->strtable[i];
45203 #endif
45204  if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
45205  continue;
45206  } else if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {
45207  DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
45208  count_keep++;
45209  continue;
45210  }
45211 
45212 #if defined(DUK_USE_DEBUG)
45213  count_free++;
45214 #endif
45215 
45216 #if defined(DUK_USE_REFERENCE_COUNTING)
45217  /* Non-zero refcounts should not happen for unreachable strings,
45218  * because we refcount finalize all unreachable objects which
45219  * should have decreased unreachable string refcounts to zero
45220  * (even for cycles).
45221  */
45222  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);
45223 #endif
45224 
45225  DUK_DDD(DUK_DDDPRINT("sweep string, not reachable: %p", (void *) h));
45226 
45227  /* deal with weak references first */
45228  duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
45229 
45230  /* remove the string (mark DELETED), could also call
45231  * duk_heap_string_remove() but that would be slow and
45232  * pointless because we already know the slot.
45233  */
45234 #if defined(DUK_USE_HEAPPTR16)
45235  heap->strtable16[i] = heap->heapptr_deleted16;
45236 #else
45237  heap->strtable[i] = DUK_STRTAB_DELETED_MARKER(heap);
45238 #endif
45239 
45240  /* free inner references (these exist e.g. when external
45241  * strings are enabled) and the struct itself.
45242  */
45243  duk_free_hstring(heap, (duk_hstring *) h);
45244  }
45245 
45246 #if defined(DUK_USE_DEBUG)
45247  DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
45248  (long) count_free, (long) count_keep));
45249 #endif
45250  *out_count_keep = count_keep;
45251 }
45252 #endif /* DUK_USE_STRTAB_PROBE */
45253 
45254 /*
45255  * Sweep heap
45256  */
45257 
45258 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_int_t flags, duk_size_t *out_count_keep) {
45259  duk_heaphdr *prev; /* last element that was left in the heap */
45260  duk_heaphdr *curr;
45261  duk_heaphdr *next;
45262 #if defined(DUK_USE_DEBUG)
45263  duk_size_t count_free = 0;
45264  duk_size_t count_finalize = 0;
45265  duk_size_t count_rescue = 0;
45266 #endif
45267  duk_size_t count_keep = 0;
45268 
45269  DUK_UNREF(flags);
45270  DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
45271 
45272  prev = NULL;
45273  curr = heap->heap_allocated;
45274  heap->heap_allocated = NULL;
45275  while (curr) {
45276  /* Strings and ROM objects are never placed on the heap allocated list. */
45277  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
45278  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
45279 
45280  next = DUK_HEAPHDR_GET_NEXT(heap, curr);
45281 
45282  if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
45283  /*
45284  * Reachable object, keep
45285  */
45286 
45287  DUK_DDD(DUK_DDDPRINT("sweep, reachable: %p", (void *) curr));
45288 
45289  if (DUK_HEAPHDR_HAS_FINALIZABLE(curr)) {
45290  /*
45291  * If object has been marked finalizable, move it to the
45292  * "to be finalized" work list. It will be collected on
45293  * the next mark-and-sweep if it is still unreachable
45294  * after running the finalizer.
45295  */
45296 
45297  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
45298  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
45299  DUK_DDD(DUK_DDDPRINT("object has finalizer, move to finalization work list: %p", (void *) curr));
45300 
45301 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
45302  if (heap->finalize_list) {
45303  DUK_HEAPHDR_SET_PREV(heap, heap->finalize_list, curr);
45304  }
45305  DUK_HEAPHDR_SET_PREV(heap, curr, NULL);
45306 #endif
45307  DUK_HEAPHDR_SET_NEXT(heap, curr, heap->finalize_list);
45308  DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
45309  heap->finalize_list = curr;
45310 #if defined(DUK_USE_DEBUG)
45311  count_finalize++;
45312 #endif
45313  } else {
45314  /*
45315  * Object will be kept; queue object back to heap_allocated (to tail)
45316  */
45317 
45318  if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
45319  /*
45320  * Object's finalizer was executed on last round, and
45321  * object has been happily rescued.
45322  */
45323 
45324  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
45325  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
45326  DUK_DD(DUK_DDPRINT("object rescued during mark-and-sweep finalization: %p", (void *) curr));
45327 #if defined(DUK_USE_DEBUG)
45328  count_rescue++;
45329 #endif
45330  } else {
45331  /*
45332  * Plain, boring reachable object.
45333  */
45334  DUK_DD(DUK_DDPRINT("keep object: %!iO", curr));
45335  count_keep++;
45336  }
45337 
45338  if (!heap->heap_allocated) {
45339  heap->heap_allocated = curr;
45340  }
45341  if (prev) {
45342  DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
45343  }
45344 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
45345  DUK_HEAPHDR_SET_PREV(heap, curr, prev);
45346 #endif
45347  DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
45348  DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
45349  prev = curr;
45350  }
45351 
45352  DUK_HEAPHDR_CLEAR_REACHABLE(curr);
45353  DUK_HEAPHDR_CLEAR_FINALIZED(curr);
45354  DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
45355 
45356  DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
45357  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
45358  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
45359 
45360  curr = next;
45361  } else {
45362  /*
45363  * Unreachable object, free
45364  */
45365 
45366  DUK_DDD(DUK_DDDPRINT("sweep, not reachable: %p", (void *) curr));
45367 
45368 #if defined(DUK_USE_REFERENCE_COUNTING)
45369  /* Non-zero refcounts should not happen because we refcount
45370  * finalize all unreachable objects which should cancel out
45371  * refcounts (even for cycles).
45372  */
45373  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
45374 #endif
45375  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
45376 
45377  if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
45378  DUK_DDD(DUK_DDDPRINT("finalized object not rescued: %p", (void *) curr));
45379  }
45380 
45381  /* Note: object cannot be a finalizable unreachable object, as
45382  * they have been marked temporarily reachable for this round,
45383  * and are handled above.
45384  */
45385 
45386 #if defined(DUK_USE_DEBUG)
45387  count_free++;
45388 #endif
45389 
45390  /* weak refs should be handled here, but no weak refs for
45391  * any non-string objects exist right now.
45392  */
45393 
45394  /* free object and all auxiliary (non-heap) allocs */
45395  duk_heap_free_heaphdr_raw(heap, curr);
45396 
45397  curr = next;
45398  }
45399  }
45400  if (prev) {
45401  DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
45402  }
45403  DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
45404 
45405 #if defined(DUK_USE_DEBUG)
45406  DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
45407  (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
45408 #endif
45409  *out_count_keep = count_keep;
45410 }
45411 
45412 /*
45413  * Run (object) finalizers in the "to be finalized" work list.
45414  */
45415 
45416 #if defined(DUK_USE_FINALIZER_SUPPORT)
45417 DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags) {
45418  duk_heaphdr *curr;
45419  duk_heaphdr *next;
45420 #if defined(DUK_USE_DEBUG)
45421  duk_size_t count = 0;
45422 #endif
45423  duk_hthread *thr;
45424 
45425  DUK_DD(DUK_DDPRINT("duk__run_object_finalizers: %p", (void *) heap));
45426 
45427  thr = duk__get_temp_hthread(heap);
45428  DUK_ASSERT(thr != NULL);
45429 
45430  curr = heap->finalize_list;
45431  while (curr) {
45432  DUK_DDD(DUK_DDDPRINT("mark-and-sweep finalize: %p", (void *) curr));
45433 
45434  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT); /* only objects have finalizers */
45435  DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr)); /* flags have been already cleared */
45436  DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
45437  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
45438  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
45439  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr)); /* No finalizers for ROM objects */
45440 
45441  if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
45442  /* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
45443  * Next mark-and-sweep will collect the object unless it has
45444  * become reachable (i.e. rescued). FINALIZED prevents the
45445  * finalizer from being executed again before that.
45446  */
45447  duk_hobject_run_finalizer(thr, (duk_hobject *) curr); /* must never longjmp */
45448  DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
45449  } else {
45450  /* Used during heap destruction: don't actually run finalizers
45451  * because we're heading into forced finalization. Instead,
45452  * queue finalizable objects back to the heap_allocated list.
45453  */
45454  DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
45455  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
45456  }
45457 
45458  /* queue back to heap_allocated */
45459  next = DUK_HEAPHDR_GET_NEXT(heap, curr);
45460  DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
45461 
45462  curr = next;
45463 #if defined(DUK_USE_DEBUG)
45464  count++;
45465 #endif
45466  }
45467 
45468  /* finalize_list will always be processed completely */
45469  heap->finalize_list = NULL;
45470 
45471 #if defined(DUK_USE_DEBUG)
45472  DUK_D(DUK_DPRINT("mark-and-sweep finalize objects: %ld finalizers called", (long) count));
45473 #endif
45474 }
45475 #endif /* DUK_USE_FINALIZER_SUPPORT */
45476 
45477 /*
45478  * Object compaction.
45479  *
45480  * Compaction is assumed to never throw an error.
45481  */
45482 
45483 DUK_LOCAL int duk__protected_compact_object(duk_context *ctx, void *udata) {
45484  duk_hobject *obj;
45485  /* XXX: for threads, compact value stack, call stack, catch stack? */
45486 
45487  DUK_UNREF(udata);
45488  obj = duk_known_hobject(ctx, -1);
45489  duk_hobject_compact_props((duk_hthread *) ctx, obj);
45490  return 0;
45491 }
45492 
45493 #if defined(DUK_USE_DEBUG)
45494 DUK_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) {
45495 #else
45496 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
45497 #endif
45498  duk_heaphdr *curr;
45499 #if defined(DUK_USE_DEBUG)
45500  duk_size_t old_size, new_size;
45501 #endif
45502  duk_hobject *obj;
45503 
45504  DUK_UNREF(heap);
45505 
45506  curr = start;
45507  while (curr) {
45508  DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
45509 
45510  if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
45511  goto next;
45512  }
45513  obj = (duk_hobject *) curr;
45514 
45515 #if defined(DUK_USE_DEBUG)
45516  old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
45517  DUK_HOBJECT_GET_ASIZE(obj),
45518  DUK_HOBJECT_GET_HSIZE(obj));
45519 #endif
45520 
45521  DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
45522  duk_push_hobject((duk_context *) thr, obj);
45523  /* XXX: disable error handlers for duration of compaction? */
45524  duk_safe_call((duk_context *) thr, duk__protected_compact_object, NULL, 1, 0);
45525 
45526 #if defined(DUK_USE_DEBUG)
45527  new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
45528  DUK_HOBJECT_GET_ASIZE(obj),
45529  DUK_HOBJECT_GET_HSIZE(obj));
45530 #endif
45531 
45532 #if defined(DUK_USE_DEBUG)
45533  (*p_count_compact)++;
45534  (*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
45535 #endif
45536 
45537  next:
45538  curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
45539 #if defined(DUK_USE_DEBUG)
45540  (*p_count_check)++;
45541 #endif
45542  }
45543 }
45544 
45545 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
45546  /* XXX: which lists should participate? to be finalized? */
45547 #if defined(DUK_USE_DEBUG)
45548  duk_size_t count_check = 0;
45549  duk_size_t count_compact = 0;
45550  duk_size_t count_bytes_saved = 0;
45551 #endif
45552  duk_hthread *thr;
45553 
45554  DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
45555 
45556  thr = duk__get_temp_hthread(heap);
45557  DUK_ASSERT(thr != NULL);
45558 
45559 #if defined(DUK_USE_DEBUG)
45560  duk__compact_object_list(heap, thr, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
45561  duk__compact_object_list(heap, thr, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
45562 #if defined(DUK_USE_REFERENCE_COUNTING)
45563  duk__compact_object_list(heap, thr, heap->refzero_list, &count_check, &count_compact, &count_bytes_saved);
45564 #endif
45565 #else
45566  duk__compact_object_list(heap, thr, heap->heap_allocated);
45567  duk__compact_object_list(heap, thr, heap->finalize_list);
45568 #if defined(DUK_USE_REFERENCE_COUNTING)
45569  duk__compact_object_list(heap, thr, heap->refzero_list);
45570 #endif
45571 #endif
45572 
45573 #if defined(DUK_USE_DEBUG)
45574  DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
45575  (long) count_check, (long) count_compact, (long) count_bytes_saved));
45576 #endif
45577 }
45578 
45579 /*
45580  * Assertion helpers.
45581  */
45582 
45583 #if defined(DUK_USE_ASSERTIONS)
45584 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
45585  duk_heaphdr *hdr;
45586 
45587  hdr = heap->heap_allocated;
45588  while (hdr) {
45589  DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
45590  DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
45591  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
45592  /* may have FINALIZED */
45593  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45594  }
45595 
45596 #if defined(DUK_USE_REFERENCE_COUNTING)
45597  hdr = heap->refzero_list;
45598  while (hdr) {
45599  DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
45600  DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
45601  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
45602  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
45603  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45604  }
45605 #endif /* DUK_USE_REFERENCE_COUNTING */
45606 }
45607 
45608 #if defined(DUK_USE_REFERENCE_COUNTING)
45609 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
45610  duk_heaphdr *hdr = heap->heap_allocated;
45611  while (hdr) {
45612  if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
45613  DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
45614  /* An object may be in heap_allocated list with a zero
45615  * refcount if it has just been finalized and is waiting
45616  * to be collected by the next cycle.
45617  */
45618  } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
45619  /* An object may be in heap_allocated list with a zero
45620  * refcount also if it is a temporary object created by
45621  * a finalizer; because finalization now runs inside
45622  * mark-and-sweep, such objects will not be queued to
45623  * refzero_list and will thus appear here with refcount
45624  * zero.
45625  */
45626 #if 0 /* this case can no longer occur because refcount is unsigned */
45627  } else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) < 0) {
45628  DUK_D(DUK_DPRINT("invalid refcount: %ld, %p -> %!O",
45629  (hdr != NULL ? (long) DUK_HEAPHDR_GET_REFCOUNT(hdr) : (long) 0),
45630  (void *) hdr, (duk_heaphdr *) hdr));
45631  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(hdr) > 0);
45632 #endif
45633  }
45634  hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
45635  }
45636 }
45637 #endif /* DUK_USE_REFERENCE_COUNTING */
45638 #endif /* DUK_USE_ASSERTIONS */
45639 
45640 /*
45641  * Finalizer torture. Do one fake finalizer call which causes side effects
45642  * similar to one or more finalizers on actual objects.
45643  */
45644 
45645 #if defined(DUK_USE_FINALIZER_SUPPORT)
45646 #if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
45647 DUK_LOCAL duk_ret_t duk__markandsweep_fake_finalizer(duk_context *ctx) {
45648  DUK_D(DUK_DPRINT("fake mark-and-sweep torture finalizer executed"));
45649 
45650  /* Require a lot of stack to force a value stack grow/shrink.
45651  * Recursive mark-and-sweep is prevented by allocation macros
45652  * so this won't trigger another mark-and-sweep.
45653  */
45654  duk_require_stack(ctx, 100000);
45655 
45656  /* XXX: do something to force a callstack grow/shrink, perhaps
45657  * just a manual forced resize or a forced relocating realloc?
45658  */
45659 
45660  return 0;
45661 }
45662 
45663 DUK_LOCAL void duk__markandsweep_torture_finalizer(duk_hthread *thr) {
45664  duk_context *ctx;
45665  duk_int_t rc;
45666 
45667  DUK_ASSERT(thr != NULL);
45668  ctx = (duk_context *) thr;
45669 
45670  /* Avoid fake finalization when callstack limit has been reached.
45671  * Otherwise a callstack limit error will be created, then refzero'ed.
45672  */
45673  if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
45674  thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
45675  DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake mark-and-sweep torture finalizer"));
45676  return;
45677  }
45678 
45679  /* Run fake finalizer. Avoid creating unnecessary garbage. */
45680  duk_push_c_function(ctx, duk__markandsweep_fake_finalizer, 0 /*nargs*/);
45681  rc = duk_pcall(ctx, 0 /*nargs*/);
45682  DUK_UNREF(rc); /* ignored */
45683  duk_pop(ctx);
45684 }
45685 #endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
45686 #endif /* DUK_USE_FINALIZER_SUPPORT */
45687 
45688 /*
45689  * Main mark-and-sweep function.
45690  *
45691  * 'flags' represents the features requested by the caller. The current
45692  * heap->mark_and_sweep_base_flags is ORed automatically into the flags;
45693  * the base flags mask typically prevents certain mark-and-sweep operations
45694  * to avoid trouble.
45695  */
45696 
45697 DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
45698  duk_hthread *thr;
45699  duk_size_t count_keep_obj;
45700  duk_size_t count_keep_str;
45701 #if defined(DUK_USE_VOLUNTARY_GC)
45702  duk_size_t tmp;
45703 #endif
45704 
45705  /* XXX: thread selection for mark-and-sweep is currently a hack.
45706  * If we don't have a thread, the entire mark-and-sweep is now
45707  * skipped (although we could just skip finalizations).
45708  */
45709 
45710  /* If thr != NULL, the thr may still be in the middle of
45711  * initialization.
45712  * XXX: Improve the thread viability test.
45713  */
45714  thr = duk__get_temp_hthread(heap);
45715  if (thr == NULL) {
45716  DUK_D(DUK_DPRINT("gc skipped because we don't have a temp thread"));
45717 
45718  /* reset voluntary gc trigger count */
45719 #if defined(DUK_USE_VOLUNTARY_GC)
45720  heap->mark_and_sweep_trigger_counter = DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP;
45721 #endif
45722  return 0; /* OK */
45723  }
45724 
45725  /* If debugger is paused, garbage collection is disabled by default. */
45726  /* XXX: will need a force flag if garbage collection is triggered
45727  * explicitly during paused state.
45728  */
45729 #if defined(DUK_USE_DEBUGGER_SUPPORT)
45730  if (DUK_HEAP_IS_PAUSED(heap)) {
45731  /* Checking this here rather that in memory alloc primitives
45732  * reduces checking code there but means a failed allocation
45733  * will go through a few retries before giving up. That's
45734  * fine because this only happens during debugging.
45735  */
45736  DUK_D(DUK_DPRINT("gc skipped because debugger is paused"));
45737  return 0;
45738  }
45739 #endif
45740 
45741  DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
45742  (unsigned long) flags, (unsigned long) (flags | heap->mark_and_sweep_base_flags)));
45743 
45744  flags |= heap->mark_and_sweep_base_flags;
45745 
45746  /*
45747  * Assertions before
45748  */
45749 
45750 #if defined(DUK_USE_ASSERTIONS)
45751  DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
45752  DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
45753  DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
45754  duk__assert_heaphdr_flags(heap);
45755 #if defined(DUK_USE_REFERENCE_COUNTING)
45756  /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
45757  * finalizer may trigger a mark-and-sweep.
45758  */
45759  duk__assert_valid_refcounts(heap);
45760 #endif /* DUK_USE_REFERENCE_COUNTING */
45761 #endif /* DUK_USE_ASSERTIONS */
45762 
45763  /*
45764  * Begin
45765  */
45766 
45767  DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap);
45768 
45769  /*
45770  * Mark roots, hoping that recursion limit is not normally hit.
45771  * If recursion limit is hit, run additional reachability rounds
45772  * starting from "temproots" until marking is complete.
45773  *
45774  * Marking happens in two phases: first we mark actual reachability
45775  * roots (and run "temproots" to complete the process). Then we
45776  * check which objects are unreachable and are finalizable; such
45777  * objects are marked as FINALIZABLE and marked as reachability
45778  * (and "temproots" is run again to complete the process).
45779  *
45780  * The heap finalize_list must also be marked as a reachability root.
45781  * There may be objects on the list from a previous round if the
45782  * previous run had finalizer skip flag.
45783  */
45784 
45785  duk__mark_roots_heap(heap); /* main reachability roots */
45786 #if defined(DUK_USE_REFERENCE_COUNTING)
45787  duk__mark_refzero_list(heap); /* refzero_list treated as reachability roots */
45788 #endif
45789  duk__mark_temproots_by_heap_scan(heap); /* temproots */
45790 
45791 #if defined(DUK_USE_FINALIZER_SUPPORT)
45792  duk__mark_finalizable(heap); /* mark finalizable as reachability roots */
45793  duk__mark_finalize_list(heap); /* mark finalizer work list as reachability roots */
45794 #endif
45795  duk__mark_temproots_by_heap_scan(heap); /* temproots */
45796 
45797  /*
45798  * Sweep garbage and remove marking flags, and move objects with
45799  * finalizers to the finalizer work list.
45800  *
45801  * Objects to be swept need to get their refcounts finalized before
45802  * they are swept. In other words, their target object refcounts
45803  * need to be decreased. This has to be done before freeing any
45804  * objects to avoid decref'ing dangling pointers (which may happen
45805  * even without bugs, e.g. with reference loops)
45806  *
45807  * Because strings don't point to other heap objects, similar
45808  * finalization is not necessary for strings.
45809  */
45810 
45811  /* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
45812 
45813 #if defined(DUK_USE_REFERENCE_COUNTING)
45814  duk__finalize_refcounts(heap);
45815 #endif
45816  duk__sweep_heap(heap, flags, &count_keep_obj);
45817 #if defined(DUK_USE_STRTAB_CHAIN)
45818  duk__sweep_stringtable_chain(heap, &count_keep_str);
45819 #elif defined(DUK_USE_STRTAB_PROBE)
45820  duk__sweep_stringtable_probe(heap, &count_keep_str);
45821 #else
45822 #error internal error, invalid strtab options
45823 #endif
45824 #if defined(DUK_USE_REFERENCE_COUNTING)
45825  duk__clear_refzero_list_flags(heap);
45826 #endif
45827 #if defined(DUK_USE_FINALIZER_SUPPORT)
45828  duk__clear_finalize_list_flags(heap);
45829 #endif
45830 
45831  /*
45832  * Object compaction (emergency only).
45833  *
45834  * Object compaction is a separate step after sweeping, as there is
45835  * more free memory for it to work with. Also, currently compaction
45836  * may insert new objects into the heap allocated list and the string
45837  * table which we don't want to do during a sweep (the reachability
45838  * flags of such objects would be incorrect). The objects inserted
45839  * are currently:
45840  *
45841  * - a temporary duk_hbuffer for a new properties allocation
45842  * - if array part is abandoned, string keys are interned
45843  *
45844  * The object insertions go to the front of the list, so they do not
45845  * cause an infinite loop (they are not compacted).
45846  */
45847 
45848  if ((flags & DUK_MS_FLAG_EMERGENCY) &&
45849  !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
45850  duk__compact_objects(heap);
45851  }
45852 
45853  /*
45854  * String table resize check.
45855  *
45856  * Note: this may silently (and safely) fail if GC is caused by an
45857  * allocation call in stringtable resize_hash(). Resize_hash()
45858  * will prevent a recursive call to itself by setting the
45859  * DUK_MS_FLAG_NO_STRINGTABLE_RESIZE in heap->mark_and_sweep_base_flags.
45860  */
45861 
45862  /* XXX: stringtable emergency compaction? */
45863 
45864  /* XXX: remove this feature entirely? it would only matter for
45865  * emergency GC. Disable for lowest memory builds.
45866  */
45867 #if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
45868  if (!(flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE)) {
45869  DUK_DD(DUK_DDPRINT("resize stringtable: %p", (void *) heap));
45870  duk_heap_force_strtab_resize(heap);
45871  } else {
45872  DUK_D(DUK_DPRINT("stringtable resize skipped because DUK_MS_FLAG_NO_STRINGTABLE_RESIZE is set"));
45873  }
45874 #endif
45875 
45876  /*
45877  * Finalize objects in the finalization work list. Finalized
45878  * objects are queued back to heap_allocated with FINALIZED set.
45879  *
45880  * Since finalizers may cause arbitrary side effects, they are
45881  * prevented during string table and object property allocation
45882  * resizing using the DUK_MS_FLAG_NO_FINALIZERS flag in
45883  * heap->mark_and_sweep_base_flags. In this case the objects
45884  * remain in the finalization work list after mark-and-sweep
45885  * exits and they may be finalized on the next pass.
45886  *
45887  * Finalization currently happens inside "MARKANDSWEEP_RUNNING"
45888  * protection (no mark-and-sweep may be triggered by the
45889  * finalizers). As a side effect:
45890  *
45891  * 1) an out-of-memory error inside a finalizer will not
45892  * cause a mark-and-sweep and may cause the finalizer
45893  * to fail unnecessarily
45894  *
45895  * 2) any temporary objects whose refcount decreases to zero
45896  * during finalization will not be put into refzero_list;
45897  * they can only be collected by another mark-and-sweep
45898  *
45899  * This is not optimal, but since the sweep for this phase has
45900  * already happened, this is probably good enough for now.
45901  */
45902 
45903 #if defined(DUK_USE_FINALIZER_SUPPORT)
45904 #if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)
45905  /* Cannot simulate individual finalizers because finalize_list only
45906  * contains objects with actual finalizers. But simulate side effects
45907  * from finalization by doing a bogus function call and resizing the
45908  * stacks.
45909  */
45910  if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
45911  DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, DUK_MS_FLAG_NO_FINALIZERS is set"));
45912  } else if (!(thr->valstack != NULL && thr->callstack != NULL && thr->catchstack != NULL)) {
45913  DUK_D(DUK_DPRINT("skip mark-and-sweep torture finalizer, thread not yet viable"));
45914  } else {
45915  DUK_D(DUK_DPRINT("run mark-and-sweep torture finalizer"));
45916  duk__markandsweep_torture_finalizer(thr);
45917  }
45918 #endif /* DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE */
45919 
45920  if (flags & DUK_MS_FLAG_NO_FINALIZERS) {
45921  DUK_D(DUK_DPRINT("finalizer run skipped because DUK_MS_FLAG_NO_FINALIZERS is set"));
45922  } else {
45923  duk__run_object_finalizers(heap, flags);
45924  }
45925 #endif /* DUK_USE_FINALIZER_SUPPORT */
45926 
45927  /*
45928  * Finish
45929  */
45930 
45931  DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap);
45932 
45933  /*
45934  * Assertions after
45935  */
45936 
45937 #if defined(DUK_USE_ASSERTIONS)
45938  DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap));
45939  DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
45940  DUK_ASSERT(heap->mark_and_sweep_recursion_depth == 0);
45941  duk__assert_heaphdr_flags(heap);
45942 #if defined(DUK_USE_REFERENCE_COUNTING)
45943  /* Note: DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) may be true; a refcount
45944  * finalizer may trigger a mark-and-sweep.
45945  */
45946  duk__assert_valid_refcounts(heap);
45947 #endif /* DUK_USE_REFERENCE_COUNTING */
45948 #endif /* DUK_USE_ASSERTIONS */
45949 
45950  /*
45951  * Reset trigger counter
45952  */
45953 
45954 #if defined(DUK_USE_VOLUNTARY_GC)
45955  tmp = (count_keep_obj + count_keep_str) / 256;
45956  heap->mark_and_sweep_trigger_counter = (duk_int_t) (
45957  (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
45958  DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
45959  DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
45960  (long) count_keep_obj, (long) count_keep_str, (long) heap->mark_and_sweep_trigger_counter));
45961 #else
45962  DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
45963  (long) count_keep_obj, (long) count_keep_str));
45964 #endif
45965 
45966  return 0; /* OK */
45967 }
45968 /*
45969  * Memory allocation handling.
45970  */
45971 
45972 /* #include duk_internal.h -> already included */
45973 
45974 /*
45975  * Helpers
45976  *
45977  * The fast path checks are done within a macro to ensure "inlining"
45978  * while the slow path actions use a helper (which won't typically be
45979  * inlined in size optimized builds).
45980  */
45981 
45982 #if defined(DUK_USE_VOLUNTARY_GC)
45983 #define DUK__VOLUNTARY_PERIODIC_GC(heap) do { \
45984  (heap)->mark_and_sweep_trigger_counter--; \
45985  if ((heap)->mark_and_sweep_trigger_counter <= 0) { \
45986  duk__run_voluntary_gc(heap); \
45987  } \
45988  } while (0)
45989 
45990 DUK_LOCAL void duk__run_voluntary_gc(duk_heap *heap) {
45991  if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
45992  DUK_DD(DUK_DDPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
45993  } else {
45994  duk_small_uint_t flags;
45995  duk_bool_t rc;
45996 
45997  DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
45998  flags = 0;
45999  rc = duk_heap_mark_and_sweep(heap, flags);
46000  DUK_UNREF(rc);
46001  }
46002 }
46003 #else
46004 #define DUK__VOLUNTARY_PERIODIC_GC(heap) /* no voluntary gc */
46005 #endif /* DUK_USE_VOLUNTARY_GC */
46006 
46007 /*
46008  * Allocate memory with garbage collection
46009  */
46010 
46011 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
46012  void *res;
46013  duk_bool_t rc;
46014  duk_small_int_t i;
46015 
46016  DUK_ASSERT(heap != NULL);
46017  DUK_ASSERT_DISABLE(size >= 0);
46018 
46019  /*
46020  * Voluntary periodic GC (if enabled)
46021  */
46022 
46023  DUK__VOLUNTARY_PERIODIC_GC(heap);
46024 
46025  /*
46026  * First attempt
46027  */
46028 
46029 #if defined(DUK_USE_GC_TORTURE)
46030  /* simulate alloc failure on every alloc (except when mark-and-sweep is running) */
46031  if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46032  DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
46033  res = NULL;
46034  DUK_UNREF(res);
46035  goto skip_attempt;
46036  }
46037 #endif
46038  res = heap->alloc_func(heap->heap_udata, size);
46039  if (res || size == 0) {
46040  /* for zero size allocations NULL is allowed */
46041  return res;
46042  }
46043 #if defined(DUK_USE_GC_TORTURE)
46044  skip_attempt:
46045 #endif
46046 
46047  DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
46048 
46049  /*
46050  * Avoid a GC if GC is already running. This can happen at a late
46051  * stage in a GC when we try to e.g. resize the stringtable
46052  * or compact objects.
46053  */
46054 
46055  if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46056  DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
46057  return NULL;
46058  }
46059 
46060  /*
46061  * Retry with several GC attempts. Initial attempts are made without
46062  * emergency mode; later attempts use emergency mode which minimizes
46063  * memory allocations forcibly.
46064  */
46065 
46066  for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
46067  duk_small_uint_t flags;
46068 
46069  flags = 0;
46070  if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
46071  flags |= DUK_MS_FLAG_EMERGENCY;
46072  }
46073 
46074  rc = duk_heap_mark_and_sweep(heap, flags);
46075  DUK_UNREF(rc);
46076 
46077  res = heap->alloc_func(heap->heap_udata, size);
46078  if (res) {
46079  DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
46080  (long) (i + 1), (long) size));
46081  return res;
46082  }
46083  }
46084 
46085  DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
46086  return NULL;
46087 }
46088 
46089 DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
46090  void *res;
46091 
46092  DUK_ASSERT(heap != NULL);
46093  DUK_ASSERT_DISABLE(size >= 0);
46094 
46095  res = DUK_ALLOC(heap, size);
46096  if (res) {
46097  /* assume memset with zero size is OK */
46098  DUK_MEMZERO(res, size);
46099  }
46100  return res;
46101 }
46102 
46103 /*
46104  * Reallocate memory with garbage collection
46105  */
46106 
46107 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
46108  void *res;
46109  duk_bool_t rc;
46110  duk_small_int_t i;
46111 
46112  DUK_ASSERT(heap != NULL);
46113  /* ptr may be NULL */
46114  DUK_ASSERT_DISABLE(newsize >= 0);
46115 
46116  /*
46117  * Voluntary periodic GC (if enabled)
46118  */
46119 
46120  DUK__VOLUNTARY_PERIODIC_GC(heap);
46121 
46122  /*
46123  * First attempt
46124  */
46125 
46126 #if defined(DUK_USE_GC_TORTURE)
46127  /* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
46128  if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46129  DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
46130  res = NULL;
46131  DUK_UNREF(res);
46132  goto skip_attempt;
46133  }
46134 #endif
46135  res = heap->realloc_func(heap->heap_udata, ptr, newsize);
46136  if (res || newsize == 0) {
46137  /* for zero size allocations NULL is allowed */
46138  return res;
46139  }
46140 #if defined(DUK_USE_GC_TORTURE)
46141  skip_attempt:
46142 #endif
46143 
46144  DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
46145 
46146  /*
46147  * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
46148  */
46149 
46150  if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46151  DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
46152  return NULL;
46153  }
46154 
46155  /*
46156  * Retry with several GC attempts. Initial attempts are made without
46157  * emergency mode; later attempts use emergency mode which minimizes
46158  * memory allocations forcibly.
46159  */
46160 
46161  for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
46162  duk_small_uint_t flags;
46163 
46164  flags = 0;
46165  if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
46166  flags |= DUK_MS_FLAG_EMERGENCY;
46167  }
46168 
46169  rc = duk_heap_mark_and_sweep(heap, flags);
46170  DUK_UNREF(rc);
46171 
46172  res = heap->realloc_func(heap->heap_udata, ptr, newsize);
46173  if (res || newsize == 0) {
46174  DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
46175  (long) (i + 1), (long) newsize));
46176  return res;
46177  }
46178  }
46179 
46180  DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
46181  return NULL;
46182 }
46183 
46184 /*
46185  * Reallocate memory with garbage collection, using a callback to provide
46186  * the current allocated pointer. This variant is used when a mark-and-sweep
46187  * (e.g. finalizers) might change the original pointer.
46188  */
46189 
46190 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
46191  void *res;
46192  duk_bool_t rc;
46193  duk_small_int_t i;
46194 
46195  DUK_ASSERT(heap != NULL);
46196  DUK_ASSERT_DISABLE(newsize >= 0);
46197 
46198  /*
46199  * Voluntary periodic GC (if enabled)
46200  */
46201 
46202  DUK__VOLUNTARY_PERIODIC_GC(heap);
46203 
46204  /*
46205  * First attempt
46206  */
46207 
46208 #if defined(DUK_USE_GC_TORTURE)
46209  /* simulate alloc failure on every realloc (except when mark-and-sweep is running) */
46210  if (!DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46211  DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
46212  res = NULL;
46213  DUK_UNREF(res);
46214  goto skip_attempt;
46215  }
46216 #endif
46217  res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
46218  if (res || newsize == 0) {
46219  /* for zero size allocations NULL is allowed */
46220  return res;
46221  }
46222 #if defined(DUK_USE_GC_TORTURE)
46223  skip_attempt:
46224 #endif
46225 
46226  DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
46227 
46228  /*
46229  * Avoid a GC if GC is already running. See duk_heap_mem_alloc().
46230  */
46231 
46232  if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
46233  DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
46234  return NULL;
46235  }
46236 
46237  /*
46238  * Retry with several GC attempts. Initial attempts are made without
46239  * emergency mode; later attempts use emergency mode which minimizes
46240  * memory allocations forcibly.
46241  */
46242 
46243  for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
46244  duk_small_uint_t flags;
46245 
46246 #if defined(DUK_USE_ASSERTIONS)
46247  void *ptr_pre; /* ptr before mark-and-sweep */
46248  void *ptr_post;
46249 #endif
46250 
46251 #if defined(DUK_USE_ASSERTIONS)
46252  ptr_pre = cb(heap, ud);
46253 #endif
46254  flags = 0;
46255  if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
46256  flags |= DUK_MS_FLAG_EMERGENCY;
46257  }
46258 
46259  rc = duk_heap_mark_and_sweep(heap, flags);
46260  DUK_UNREF(rc);
46261 #if defined(DUK_USE_ASSERTIONS)
46262  ptr_post = cb(heap, ud);
46263  if (ptr_pre != ptr_post) {
46264  /* useful for debugging */
46265  DUK_DD(DUK_DDPRINT("note: base pointer changed by mark-and-sweep: %p -> %p",
46266  (void *) ptr_pre, (void *) ptr_post));
46267  }
46268 #endif
46269 
46270  /* Note: key issue here is to re-lookup the base pointer on every attempt.
46271  * The pointer being reallocated may change after every mark-and-sweep.
46272  */
46273 
46274  res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
46275  if (res || newsize == 0) {
46276  DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
46277  (long) (i + 1), (long) newsize));
46278  return res;
46279  }
46280  }
46281 
46282  DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
46283  return NULL;
46284 }
46285 
46286 /*
46287  * Free memory
46288  */
46289 
46290 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
46291  DUK_ASSERT(heap != NULL);
46292  /* ptr may be NULL */
46293 
46294  /* Must behave like a no-op with NULL and any pointer returned from
46295  * malloc/realloc with zero size.
46296  */
46297  heap->free_func(heap->heap_udata, ptr);
46298 
46299  /* Count free operations toward triggering a GC but never actually trigger
46300  * a GC from a free. Otherwise code which frees internal structures would
46301  * need to put in NULLs at every turn to ensure the object is always in
46302  * consistent state for a mark-and-sweep.
46303  */
46304 #if defined(DUK_USE_VOLUNTARY_GC)
46305  heap->mark_and_sweep_trigger_counter--;
46306 #endif
46307 }
46308 
46309 /* automatic undefs */
46310 #undef DUK__VOLUNTARY_PERIODIC_GC
46311 /*
46312  * Support functions for duk_heap.
46313  */
46314 
46315 /* #include duk_internal.h -> already included */
46316 
46317 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING)
46318 /* arbitrary remove only works with double linked heap, and is only required by
46319  * reference counting so far.
46320  */
46321 DUK_INTERNAL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
46322  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
46323 
46324  if (DUK_HEAPHDR_GET_PREV(heap, hdr)) {
46325  DUK_HEAPHDR_SET_NEXT(heap, DUK_HEAPHDR_GET_PREV(heap, hdr), DUK_HEAPHDR_GET_NEXT(heap, hdr));
46326  } else {
46327  heap->heap_allocated = DUK_HEAPHDR_GET_NEXT(heap, hdr);
46328  }
46329  if (DUK_HEAPHDR_GET_NEXT(heap, hdr)) {
46330  DUK_HEAPHDR_SET_PREV(heap, DUK_HEAPHDR_GET_NEXT(heap, hdr), DUK_HEAPHDR_GET_PREV(heap, hdr));
46331  } else {
46332  ;
46333  }
46334 
46335  /* The prev/next pointers of the removed duk_heaphdr are left as garbage.
46336  * It's up to the caller to ensure they're written before inserting the
46337  * object back.
46338  */
46339 }
46340 #endif
46341 
46342 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
46343  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
46344 
46345 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
46346  if (heap->heap_allocated) {
46347  DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, heap->heap_allocated) == NULL);
46348  DUK_HEAPHDR_SET_PREV(heap, heap->heap_allocated, hdr);
46349  }
46350  DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
46351 #endif
46352  DUK_HEAPHDR_SET_NEXT(heap, hdr, heap->heap_allocated);
46353  heap->heap_allocated = hdr;
46354 }
46355 
46356 #if defined(DUK_USE_INTERRUPT_COUNTER)
46357 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
46358  duk_hthread *curr_thr;
46359 
46360  DUK_ASSERT(heap != NULL);
46361 
46362  if (new_thr != NULL) {
46363  curr_thr = heap->curr_thread;
46364  if (curr_thr == NULL) {
46365  /* For initial entry use default value; zero forces an
46366  * interrupt before executing the first insturction.
46367  */
46368  DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
46369  new_thr->interrupt_counter = 0;
46370  new_thr->interrupt_init = 0;
46371  } else {
46372  /* Copy interrupt counter/init value state to new thread (if any).
46373  * It's OK for new_thr to be the same as curr_thr.
46374  */
46375 #if defined(DUK_USE_DEBUG)
46376  if (new_thr != curr_thr) {
46377  DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
46378  }
46379 #endif
46380  new_thr->interrupt_counter = curr_thr->interrupt_counter;
46381  new_thr->interrupt_init = curr_thr->interrupt_init;
46382  }
46383  } else {
46384  DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
46385  }
46386 
46387  heap->curr_thread = new_thr; /* may be NULL */
46388 }
46389 #endif /* DUK_USE_INTERRUPT_COUNTER */
46390 /*
46391  * Reference counting implementation.
46392  */
46393 
46394 /* #include duk_internal.h -> already included */
46395 
46396 #if defined(DUK_USE_REFERENCE_COUNTING)
46397 
46398 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
46399 #error internal error, reference counting requires a double linked heap
46400 #endif
46401 
46402 /*
46403  * Misc
46404  */
46405 
46406 DUK_LOCAL void duk__queue_refzero(duk_heap *heap, duk_heaphdr *hdr) {
46407  /* tail insert: don't disturb head in case refzero is running */
46408 
46409  if (heap->refzero_list != NULL) {
46410  duk_heaphdr *hdr_prev;
46411 
46412  hdr_prev = heap->refzero_list_tail;
46413  DUK_ASSERT(hdr_prev != NULL);
46414  DUK_ASSERT(DUK_HEAPHDR_GET_NEXT(heap, hdr_prev) == NULL);
46415 
46416  DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
46417  DUK_HEAPHDR_SET_PREV(heap, hdr, hdr_prev);
46418  DUK_HEAPHDR_SET_NEXT(heap, hdr_prev, hdr);
46419  DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
46420  DUK_ASSERT_HEAPHDR_LINKS(heap, hdr_prev);
46421  heap->refzero_list_tail = hdr;
46422  } else {
46423  DUK_ASSERT(heap->refzero_list_tail == NULL);
46424  DUK_HEAPHDR_SET_NEXT(heap, hdr, NULL);
46425  DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
46426  DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
46427  heap->refzero_list = hdr;
46428  heap->refzero_list_tail = hdr;
46429  }
46430 }
46431 
46432 /*
46433  * Heap object refcount finalization.
46434  *
46435  * When an object is about to be freed, all other objects it refers to must
46436  * be decref'd. Refcount finalization does NOT free the object or its inner
46437  * allocations (mark-and-sweep shares these helpers), it just manipulates
46438  * the refcounts.
46439  *
46440  * Note that any of the decref's may cause a refcount to drop to zero, BUT
46441  * it will not be processed inline. If refcount finalization is triggered
46442  * by refzero processing, the objects will be just queued to the refzero
46443  * list and processed later which eliminates C recursion. If refcount
46444  * finalization is triggered by mark-and-sweep, any refzero situations are
46445  * ignored because mark-and-sweep will deal with them. NORZ variants can
46446  * be used here in both cases.
46447  */
46448 
46449 DUK_LOCAL void duk__refcount_finalize_hobject(duk_hthread *thr, duk_hobject *h) {
46450  duk_uint_fast32_t i;
46451  duk_uint_fast32_t n;
46452  duk_propvalue *p_val;
46453  duk_tval *p_tv;
46454  duk_hstring **p_key;
46455  duk_uint8_t *p_flag;
46456 
46457  DUK_ASSERT(h);
46458  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
46459 
46460  /* XXX: better to get base and walk forwards? */
46461 
46462  p_key = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h);
46463  p_val = DUK_HOBJECT_E_GET_VALUE_BASE(thr->heap, h);
46464  p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(thr->heap, h);
46465  n = DUK_HOBJECT_GET_ENEXT(h);
46466  while (n-- > 0) {
46467  duk_hstring *key;
46468 
46469  key = p_key[n];
46470  if (!key) {
46471  continue;
46472  }
46473  DUK_HSTRING_DECREF_NORZ(thr, key);
46474  if (p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR) {
46475  duk_hobject *h_getset;
46476  h_getset = p_val[n].a.get;
46477  DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
46478  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
46479  h_getset = p_val[n].a.set;
46480  DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
46481  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
46482  } else {
46483  duk_tval *tv_val;
46484  tv_val = &p_val[n].v;
46485  DUK_TVAL_DECREF_NORZ(thr, tv_val);
46486  }
46487  }
46488 
46489  p_tv = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
46490  n = DUK_HOBJECT_GET_ASIZE(h);
46491  while (n-- > 0) {
46492  duk_tval *tv_val;
46493  tv_val = p_tv + n;
46494  DUK_TVAL_DECREF_NORZ(thr, tv_val);
46495  }
46496 
46497  /* hash part is a 'weak reference' and does not contribute */
46498 
46499  {
46500  duk_hobject *h_proto;
46501  h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
46502  DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
46503  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
46504  }
46505 
46506  /* XXX: rearrange bits to allow a switch case to be used here? */
46507  /* XXX: add a fast path for objects (and arrays)? */
46508 
46509  /* DUK_HOBJECT_IS_ARRAY(h): needs no special handling now as there are
46510  * no extra fields in need of decref.
46511  */
46512  if (DUK_HOBJECT_IS_COMPFUNC(h)) {
46513  duk_hcompfunc *f = (duk_hcompfunc *) h;
46514  duk_tval *tv, *tv_end;
46515  duk_hobject **funcs, **funcs_end;
46516 
46517  if (DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL) {
46518  tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
46519  tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
46520  while (tv < tv_end) {
46521  DUK_TVAL_DECREF_NORZ(thr, tv);
46522  tv++;
46523  }
46524 
46525  funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
46526  funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
46527  while (funcs < funcs_end) {
46528  duk_hobject *h_func;
46529  h_func = *funcs;
46530  DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
46531  DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
46532  funcs++;
46533  }
46534  } else {
46535  /* May happen in some out-of-memory corner cases. */
46536  DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
46537  }
46538 
46539  DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f));
46540  DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(thr->heap, f));
46541  DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, f));
46542  } else if (DUK_HOBJECT_IS_NATFUNC(h)) {
46543  duk_hnatfunc *f = (duk_hnatfunc *) h;
46544  DUK_UNREF(f);
46545  /* nothing to finalize */
46546 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
46547  } else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
46548  duk_hbufobj *b = (duk_hbufobj *) h;
46549  DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
46550  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
46551 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
46552  } else if (DUK_HOBJECT_IS_THREAD(h)) {
46553  duk_hthread *t = (duk_hthread *) h;
46554  duk_tval *tv;
46555 
46556  tv = t->valstack;
46557  while (tv < t->valstack_top) {
46558  DUK_TVAL_DECREF_NORZ(thr, tv);
46559  tv++;
46560  }
46561 
46562  for (i = 0; i < (duk_uint_fast32_t) t->callstack_top; i++) {
46563  duk_activation *act = t->callstack + i;
46564  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
46565  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
46566  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
46567 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
46568  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
46569 #endif
46570  }
46571 
46572 #if 0 /* nothing now */
46573  for (i = 0; i < (duk_uint_fast32_t) t->catchstack_top; i++) {
46574  duk_catcher *cat = t->catchstack + i;
46575  }
46576 #endif
46577 
46578  for (i = 0; i < DUK_NUM_BUILTINS; i++) {
46579  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
46580  }
46581 
46582  DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
46583  }
46584 }
46585 
46586 DUK_INTERNAL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr) {
46587  DUK_ASSERT(hdr);
46588 
46589  if (DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_OBJECT) {
46590  duk__refcount_finalize_hobject(thr, (duk_hobject *) hdr);
46591  }
46592  /* DUK_HTYPE_BUFFER: nothing to finalize */
46593  /* DUK_HTYPE_STRING: nothing to finalize */
46594 }
46595 
46596 #if defined(DUK_USE_FINALIZER_SUPPORT)
46597 #if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
46598 DUK_LOCAL duk_ret_t duk__refcount_fake_finalizer(duk_context *ctx) {
46599  DUK_UNREF(ctx);
46600  DUK_D(DUK_DPRINT("fake refcount torture finalizer executed"));
46601 #if 0
46602  DUK_DD(DUK_DDPRINT("fake torture finalizer for: %!T", duk_get_tval(ctx, 0)));
46603 #endif
46604  /* Require a lot of stack to force a value stack grow/shrink. */
46605  duk_require_stack(ctx, 100000);
46606 
46607  /* XXX: do something to force a callstack grow/shrink, perhaps
46608  * just a manual forced resize?
46609  */
46610  return 0;
46611 }
46612 
46613 DUK_LOCAL void duk__refcount_run_torture_finalizer(duk_hthread *thr, duk_hobject *obj) {
46614  duk_context *ctx;
46615  duk_int_t rc;
46616 
46617  DUK_ASSERT(thr != NULL);
46618  DUK_ASSERT(obj != NULL);
46619  ctx = (duk_context *) thr;
46620 
46621  /* Avoid fake finalization for the duk__refcount_fake_finalizer function
46622  * itself, otherwise we're in infinite recursion.
46623  */
46624  if (DUK_HOBJECT_HAS_NATFUNC(obj)) {
46625  if (((duk_hnatfunc *) obj)->func == duk__refcount_fake_finalizer) {
46626  DUK_DD(DUK_DDPRINT("avoid fake torture finalizer for duk__refcount_fake_finalizer itself"));
46627  return;
46628  }
46629  }
46630  /* Avoid fake finalization when callstack limit has been reached.
46631  * Otherwise a callstack limit error will be created, then refzero'ed,
46632  * and we're in an infinite loop.
46633  */
46634  if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit ||
46635  thr->callstack_size + 2 * DUK_CALLSTACK_GROW_STEP >= thr->callstack_max /*approximate*/) {
46636  DUK_D(DUK_DPRINT("call recursion depth reached, avoid fake torture finalizer"));
46637  return;
46638  }
46639 
46640  /* Run fake finalizer. Avoid creating new refzero queue entries
46641  * so that we are not forced into a forever loop.
46642  */
46643  duk_push_c_function(ctx, duk__refcount_fake_finalizer, 1 /*nargs*/);
46644  duk_push_hobject(ctx, obj);
46645  rc = duk_pcall(ctx, 1);
46646  DUK_UNREF(rc); /* ignored */
46647  duk_pop(ctx);
46648 }
46649 #endif /* DUK_USE_REFZERO_FINALIZER_TORTURE */
46650 #endif /* DUK_USE_FINALIZER_SUPPORT */
46651 
46652 /*
46653  * Refcount memory freeing loop.
46654  *
46655  * Frees objects in the refzero_pending list until the list becomes
46656  * empty. When an object is freed, its references get decref'd and
46657  * may cause further objects to be queued for freeing.
46658  *
46659  * This could be expanded to allow incremental freeing: just bail out
46660  * early and resume at a future alloc/decref/refzero.
46661  */
46662 
46663 DUK_INTERNAL void duk_refzero_free_pending(duk_hthread *thr) {
46664  duk_heaphdr *h1, *h2;
46665  duk_heap *heap;
46666  duk_int_t count = 0;
46667 
46668  DUK_ASSERT(thr != NULL);
46669  DUK_ASSERT(thr->heap != NULL);
46670  heap = thr->heap;
46671  DUK_ASSERT(heap != NULL);
46672 
46673  /*
46674  * Detect recursive invocation
46675  */
46676 
46677  if (DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap)) {
46678  DUK_DDD(DUK_DDDPRINT("refzero free running, skip run"));
46679  return;
46680  }
46681 
46682  /*
46683  * Churn refzero_list until empty
46684  */
46685 
46686  DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap);
46687  while (heap->refzero_list) {
46688  duk_hobject *obj;
46689 #if defined(DUK_USE_FINALIZER_SUPPORT)
46690  duk_bool_t rescued = 0;
46691 #endif /* DUK_USE_FINALIZER_SUPPORT */
46692 
46693  /*
46694  * Pick an object from the head (don't remove yet).
46695  */
46696 
46697  h1 = heap->refzero_list;
46698  obj = (duk_hobject *) h1;
46699  DUK_DD(DUK_DDPRINT("refzero processing %p: %!O", (void *) h1, (duk_heaphdr *) h1));
46700  DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, h1) == NULL);
46701  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT); /* currently, always the case */
46702 
46703 #if defined(DUK_USE_FINALIZER_SUPPORT)
46704 #if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)
46705  /* Torture option to shake out finalizer side effect issues:
46706  * make a bogus function call for every finalizable object,
46707  * essentially simulating the case where everything has a
46708  * finalizer.
46709  */
46710  DUK_DD(DUK_DDPRINT("refzero torture enabled, fake finalizer"));
46711  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
46712  DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
46713  duk__refcount_run_torture_finalizer(thr, obj); /* must never longjmp */
46714  DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
46715  DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
46716 #endif /* DUK_USE_REFZERO_FINALIZER_TORTURE */
46717 #endif /* DUK_USE_FINALIZER_SUPPORT */
46718 
46719  /*
46720  * Finalizer check.
46721  *
46722  * Note: running a finalizer may have arbitrary side effects, e.g.
46723  * queue more objects on refzero_list (tail), or even trigger a
46724  * mark-and-sweep.
46725  *
46726  * Note: quick reject check should match vast majority of
46727  * objects and must be safe (not throw any errors, ever).
46728  *
46729  * An object may have FINALIZED here if it was finalized by mark-and-sweep
46730  * on a previous run and refcount then decreased to zero. We won't run the
46731  * finalizer again here.
46732  *
46733  * A finalizer is looked up from the object and up its prototype chain
46734  * (which allows inherited finalizers).
46735  */
46736 
46737 #if defined(DUK_USE_FINALIZER_SUPPORT)
46738  if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_FINALIZER(thr))) {
46739  DUK_DDD(DUK_DDDPRINT("object has a finalizer, run it"));
46740 
46741  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h1) == 0);
46742  DUK_HEAPHDR_PREINC_REFCOUNT(h1); /* bump refcount to prevent refzero during finalizer processing */
46743 
46744  duk_hobject_run_finalizer(thr, obj); /* must never longjmp */
46745  DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1)); /* duk_hobject_run_finalizer() sets */
46746 
46747  DUK_HEAPHDR_PREDEC_REFCOUNT(h1); /* remove artificial bump */
46748  DUK_ASSERT_DISABLE(h1->h_refcount >= 0); /* refcount is unsigned, so always true */
46749 
46750  if (DUK_HEAPHDR_GET_REFCOUNT(h1) != 0) {
46751  DUK_DDD(DUK_DDDPRINT("-> object refcount after finalization non-zero, object will be rescued"));
46752  rescued = 1;
46753  } else {
46754  DUK_DDD(DUK_DDDPRINT("-> object refcount still zero after finalization, object will be freed"));
46755  }
46756  }
46757 #endif /* DUK_USE_FINALIZER_SUPPORT */
46758 
46759  /* Refzero head is still the same. This is the case even if finalizer
46760  * inserted more refzero objects; they are inserted to the tail.
46761  */
46762  DUK_ASSERT(h1 == heap->refzero_list);
46763 
46764  /*
46765  * Remove the object from the refzero list. This cannot be done
46766  * before a possible finalizer has been executed; the finalizer
46767  * may trigger a mark-and-sweep, and mark-and-sweep must be able
46768  * to traverse a complete refzero_list.
46769  */
46770 
46771  h2 = DUK_HEAPHDR_GET_NEXT(heap, h1);
46772  if (h2) {
46773  DUK_HEAPHDR_SET_PREV(heap, h2, NULL); /* not strictly necessary */
46774  heap->refzero_list = h2;
46775  } else {
46776  heap->refzero_list = NULL;
46777  heap->refzero_list_tail = NULL;
46778  }
46779 
46780  /*
46781  * Rescue or free.
46782  */
46783 
46784 #if defined(DUK_USE_FINALIZER_SUPPORT)
46785  if (rescued) {
46786  /* yes -> move back to heap allocated */
46787  DUK_DD(DUK_DDPRINT("object rescued during refcount finalization: %p", (void *) h1));
46788  DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(h1));
46789  DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(h1));
46790  DUK_HEAPHDR_CLEAR_FINALIZED(h1);
46791  h2 = heap->heap_allocated;
46792  DUK_HEAPHDR_SET_PREV(heap, h1, NULL);
46793  if (h2) {
46794  DUK_HEAPHDR_SET_PREV(heap, h2, h1);
46795  }
46796  DUK_HEAPHDR_SET_NEXT(heap, h1, h2);
46797  DUK_ASSERT_HEAPHDR_LINKS(heap, h1);
46798  DUK_ASSERT_HEAPHDR_LINKS(heap, h2);
46799  heap->heap_allocated = h1;
46800  } else
46801 #endif /* DUK_USE_FINALIZER_SUPPORT */
46802  {
46803  /* no -> decref members, then free */
46804  duk__refcount_finalize_hobject(thr, obj);
46805  DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h1) == DUK_HTYPE_OBJECT); /* currently, always the case */
46806  duk_free_hobject(heap, (duk_hobject *) h1);
46807  }
46808 
46809  count++;
46810  }
46811  DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap);
46812 
46813  DUK_DDD(DUK_DDDPRINT("refzero processed %ld objects", (long) count));
46814 
46815  /*
46816  * Once the whole refzero cascade has been freed, check for
46817  * a voluntary mark-and-sweep.
46818  */
46819 
46820 #if defined(DUK_USE_VOLUNTARY_GC)
46821  /* 'count' is more or less comparable to normal trigger counter update
46822  * which happens in memory block (re)allocation.
46823  */
46824  heap->mark_and_sweep_trigger_counter -= count;
46825  if (heap->mark_and_sweep_trigger_counter <= 0) {
46826  duk_bool_t rc;
46827  duk_small_uint_t flags = 0; /* not emergency */
46828  DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
46829  rc = duk_heap_mark_and_sweep(heap, flags);
46830  DUK_UNREF(rc);
46831  DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
46832  }
46833 #endif /* DUK_USE_VOLUNTARY_GC */
46834 }
46835 
46836 /*
46837  * Incref and decref functions.
46838  *
46839  * Decref may trigger immediate refzero handling, which may free and finalize
46840  * an arbitrary number of objects.
46841  *
46842  * Refzero handling is skipped entirely if (1) mark-and-sweep is running or
46843  * (2) execution is paused in the debugger. The objects are left in the heap,
46844  * and will be freed by mark-and-sweep or eventual heap destruction.
46845  *
46846  * This is necessary during mark-and-sweep because refcounts are also updated
46847  * during the sweep phase (otherwise objects referenced by a swept object
46848  * would have incorrect refcounts) which then calls here. This could be
46849  * avoided by using separate decref macros in mark-and-sweep; however,
46850  * mark-and-sweep also calls finalizers which would use the ordinary decref
46851  * macros anyway.
46852  *
46853  * The DUK__RZ_SUPPRESS_CHECK() must be enabled also when mark-and-sweep
46854  * support has been disabled: the flag is also used in heap destruction when
46855  * running finalizers for remaining objects, and the flag prevents objects
46856  * from being moved around in heap linked lists.
46857  */
46858 
46859 /* The suppress condition is important to performance. The flags being tested
46860  * are in the same duk_heap field so a single TEST instruction (on x86) tests
46861  * for them.
46862  */
46863 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46864 #define DUK__RZ_SUPPRESS_COND() \
46865  (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) || DUK_HEAP_IS_PAUSED(heap))
46866 #else
46867 #define DUK__RZ_SUPPRESS_COND() \
46868  (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap))
46869 #endif
46870 #define DUK__RZ_SUPPRESS_CHECK() do { \
46871  if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
46872  DUK_DDD(DUK_DDDPRINT("refzero handling suppressed when mark-and-sweep running, object: %p", (void *) h)); \
46873  return; \
46874  } \
46875  } while (0)
46876 
46877 #define DUK__RZ_STRING() do { \
46878  duk_heap_strcache_string_remove(thr->heap, (duk_hstring *) h); \
46879  duk_heap_string_remove(heap, (duk_hstring *) h); \
46880  duk_free_hstring(heap, (duk_hstring *) h); \
46881  } while (0)
46882 #define DUK__RZ_BUFFER() do { \
46883  duk_heap_remove_any_from_heap_allocated(heap, (duk_heaphdr *) h); \
46884  duk_free_hbuffer(heap, (duk_hbuffer *) h); \
46885  } while (0)
46886 #define DUK__RZ_OBJECT() do { \
46887  duk_heap_remove_any_from_heap_allocated(heap, (duk_heaphdr *) h); \
46888  duk__queue_refzero(heap, (duk_heaphdr *) h); \
46889  if (!skip_free_pending) { \
46890  duk_refzero_free_pending(thr); \
46891  } \
46892  } while (0)
46893 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
46894 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
46895 #else
46896 #define DUK__RZ_INLINE /*nop*/
46897 #endif
46898 
46899 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
46900  duk_heap *heap;
46901 
46902  DUK_ASSERT(thr != NULL);
46903  DUK_ASSERT(h != NULL);
46904  heap = thr->heap;
46905 
46906  DUK__RZ_SUPPRESS_CHECK();
46907  DUK__RZ_STRING();
46908 }
46909 
46910 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
46911  duk_heap *heap;
46912 
46913  DUK_ASSERT(thr != NULL);
46914  DUK_ASSERT(h != NULL);
46915  heap = thr->heap;
46916 
46917  DUK__RZ_SUPPRESS_CHECK();
46918  DUK__RZ_BUFFER();
46919 }
46920 
46921 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
46922  duk_heap *heap;
46923 
46924  DUK_ASSERT(thr != NULL);
46925  DUK_ASSERT(h != NULL);
46926  heap = thr->heap;
46927 
46928  DUK__RZ_SUPPRESS_CHECK();
46929  DUK__RZ_OBJECT();
46930 }
46931 
46932 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
46933  duk_heap *heap;
46934  duk_small_uint_t htype;
46935 
46936  DUK_ASSERT(thr != NULL);
46937  DUK_ASSERT(h != NULL);
46938  heap = thr->heap;
46939 
46940  htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
46941  DUK__RZ_SUPPRESS_CHECK();
46942 
46943  switch (htype) {
46944  case DUK_HTYPE_STRING:
46945  /* Strings have no internal references but do have "weak"
46946  * references in the string cache. Also note that strings
46947  * are not on the heap_allocated list like other heap
46948  * elements.
46949  */
46950 
46951  DUK__RZ_STRING();
46952  break;
46953 
46954  case DUK_HTYPE_OBJECT:
46955  /* Objects have internal references. Must finalize through
46956  * the "refzero" work list.
46957  */
46958 
46959  DUK__RZ_OBJECT();
46960  break;
46961 
46962  case DUK_HTYPE_BUFFER:
46963  /* Buffers have no internal references. However, a dynamic
46964  * buffer has a separate allocation for the buffer. This is
46965  * freed by duk_heap_free_heaphdr_raw().
46966  */
46967 
46968  DUK__RZ_BUFFER();
46969  break;
46970 
46971  default:
46972  DUK_D(DUK_DPRINT("invalid heap type in decref: %ld", (long) DUK_HEAPHDR_GET_TYPE(h)));
46973  DUK_UNREACHABLE();
46974  }
46975 }
46976 
46977 DUK_INTERNAL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
46978  duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
46979 }
46980 
46981 DUK_INTERNAL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
46982  duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
46983 }
46984 
46985 DUK_INTERNAL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
46986  duk__hstring_refzero_helper(thr, h);
46987 }
46988 
46989 DUK_INTERNAL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
46990  duk__hbuffer_refzero_helper(thr, h);
46991 }
46992 
46993 DUK_INTERNAL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
46994  duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
46995 }
46996 
46997 DUK_INTERNAL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
46998  duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
46999 }
47000 
47001 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
47002 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
47003  DUK_ASSERT(tv != NULL);
47004 
47005  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
47006  duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
47007  DUK_ASSERT(h != NULL);
47008  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
47009  DUK_ASSERT_DISABLE(h->h_refcount >= 0);
47010  DUK_HEAPHDR_PREINC_REFCOUNT(h);
47011  }
47012 }
47013 
47014 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
47015  DUK_ASSERT(thr != NULL);
47016  DUK_ASSERT(tv != NULL);
47017 
47018  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
47019  duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
47020  DUK_ASSERT(h != NULL);
47021  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
47022  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
47023 #if 0
47024  if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
47025  return;
47026  }
47027  duk_heaphdr_refzero(thr, h);
47028 #else
47029  duk_heaphdr_decref(thr, h);
47030 #endif
47031  }
47032 }
47033 
47034 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
47035  DUK_ASSERT(thr != NULL);
47036  DUK_ASSERT(tv != NULL);
47037 
47038  if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
47039  duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
47040  DUK_ASSERT(h != NULL);
47041  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
47042  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
47043 #if 0
47044  if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
47045  return;
47046  }
47047  duk_heaphdr_refzero_norz(thr, h);
47048 #else
47049  duk_heaphdr_decref(thr, h);
47050 #endif
47051  }
47052 }
47053 #endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
47054 
47055 #define DUK__DECREF_ASSERTS() do { \
47056  DUK_ASSERT(thr != NULL); \
47057  DUK_ASSERT(thr->heap != NULL); \
47058  DUK_ASSERT(h != NULL); \
47059  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
47060  DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
47061  } while (0)
47062 #if defined(DUK_USE_ROM_OBJECTS)
47063 #define DUK__DECREF_SHARED() do { \
47064  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
47065  return; \
47066  } \
47067  if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
47068  return; \
47069  } \
47070  } while (0)
47071 #else
47072 #define DUK__DECREF_SHARED() do { \
47073  if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
47074  return; \
47075  } \
47076  } while (0)
47077 #endif
47078 
47079 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
47080 /* This will in practice be inlined because it's just an INC instructions
47081  * and a bit test + INC when ROM objects are enabled.
47082  */
47083 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
47084  DUK_ASSERT(h != NULL);
47085  DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
47086  DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
47087 
47088  DUK_HEAPHDR_PREINC_REFCOUNT(h);
47089 }
47090 
47091 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
47092  DUK__DECREF_ASSERTS();
47093  DUK__DECREF_SHARED();
47094  duk_heaphdr_refzero(thr, h);
47095 }
47096 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
47097  DUK__DECREF_ASSERTS();
47098  DUK__DECREF_SHARED();
47099  duk_heaphdr_refzero_norz(thr, h);
47100 }
47101 #endif /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
47102 
47103 #if 0 /* Not needed. */
47104 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
47105  DUK__DECREF_ASSERTS();
47106  DUK__DECREF_SHARED();
47107  duk_hstring_refzero(thr, h);
47108 }
47109 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
47110  DUK__DECREF_ASSERTS();
47111  DUK__DECREF_SHARED();
47112  duk_hstring_refzero_norz(thr, h);
47113 }
47114 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
47115  DUK__DECREF_ASSERTS();
47116  DUK__DECREF_SHARED();
47117  duk_hbuffer_refzero(thr, h);
47118 }
47119 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
47120  DUK__DECREF_ASSERTS();
47121  DUK__DECREF_SHARED();
47122  duk_hbuffer_refzero_norz(thr, h);
47123 }
47124 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
47125  DUK__DECREF_ASSERTS();
47126  DUK__DECREF_SHARED();
47127  duk_hobject_refzero(thr, h);
47128 }
47129 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
47130  DUK__DECREF_ASSERTS();
47131  DUK__DECREF_SHARED();
47132  duk_hobject_refzero_norz(thr, h);
47133 }
47134 #endif
47135 
47136 #else /* DUK_USE_REFERENCE_COUNTING */
47137 
47138 /* no refcounting */
47139 
47140 #endif /* DUK_USE_REFERENCE_COUNTING */
47141 
47142 /* automatic undefs */
47143 #undef DUK__DECREF_ASSERTS
47144 #undef DUK__DECREF_SHARED
47145 #undef DUK__RZ_BUFFER
47146 #undef DUK__RZ_INLINE
47147 #undef DUK__RZ_OBJECT
47148 #undef DUK__RZ_STRING
47149 #undef DUK__RZ_SUPPRESS_CHECK
47150 #undef DUK__RZ_SUPPRESS_COND
47151 /*
47152  * String cache.
47153  *
47154  * Provides a cache to optimize indexed string lookups. The cache keeps
47155  * track of (byte offset, char offset) states for a fixed number of strings.
47156  * Otherwise we'd need to scan from either end of the string, as we store
47157  * strings in (extended) UTF-8.
47158  */
47159 
47160 /* #include duk_internal.h -> already included */
47161 
47162 /*
47163  * Delete references to given hstring from the heap string cache.
47164  *
47165  * String cache references are 'weak': they are not counted towards
47166  * reference counts, nor serve as roots for mark-and-sweep. When an
47167  * object is about to be freed, such references need to be removed.
47168  */
47169 
47170 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
47171  duk_small_int_t i;
47172  for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
47173  duk_strcache *c = heap->strcache + i;
47174  if (c->h == h) {
47175  DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
47176  (void *) h, (void *) heap));
47177  c->h = NULL;
47178 
47179  /* XXX: the string shouldn't appear twice, but we now loop to the
47180  * end anyway; if fixed, add a looping assertion to ensure there
47181  * is no duplicate.
47182  */
47183  }
47184  }
47185 }
47186 
47187 /*
47188  * String scanning helpers
47189  *
47190  * All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
47191  * considered to contribute a character. This must match how string
47192  * character length is computed.
47193  */
47194 
47195 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
47196  while (n > 0) {
47197  for (;;) {
47198  p++;
47199  if (p >= q) {
47200  return NULL;
47201  }
47202  if ((*p & 0xc0) != 0x80) {
47203  break;
47204  }
47205  }
47206  n--;
47207  }
47208  return p;
47209 }
47210 
47211 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
47212  while (n > 0) {
47213  for (;;) {
47214  p--;
47215  if (p < q) {
47216  return NULL;
47217  }
47218  if ((*p & 0xc0) != 0x80) {
47219  break;
47220  }
47221  }
47222  n--;
47223  }
47224  return p;
47225 }
47226 
47227 /*
47228  * Convert char offset to byte offset
47229  *
47230  * Avoid using the string cache if possible: for ASCII strings byte and
47231  * char offsets are equal and for short strings direct scanning may be
47232  * better than using the string cache (which may evict a more important
47233  * entry).
47234  *
47235  * Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
47236  * Better typing might be to use duk_size_t.
47237  */
47238 
47239 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
47240  duk_heap *heap;
47241  duk_strcache *sce;
47242  duk_uint_fast32_t byte_offset;
47243  duk_small_int_t i;
47244  duk_bool_t use_cache;
47245  duk_uint_fast32_t dist_start, dist_end, dist_sce;
47246  const duk_uint8_t *p_start;
47247  const duk_uint8_t *p_end;
47248  const duk_uint8_t *p_found;
47249 
47250  if (char_offset > DUK_HSTRING_GET_CHARLEN(h)) {
47251  goto error;
47252  }
47253 
47254  /*
47255  * For ASCII strings, the answer is simple.
47256  */
47257 
47258  if (DUK_HSTRING_IS_ASCII(h)) {
47259  /* clen == blen -> pure ascii */
47260  return char_offset;
47261  }
47262 
47263  /*
47264  * For non-ASCII strings, we need to scan forwards or backwards
47265  * from some starting point. The starting point may be the start
47266  * or end of the string, or some cached midpoint in the string
47267  * cache.
47268  *
47269  * For "short" strings we simply scan without checking or updating
47270  * the cache. For longer strings we check and update the cache as
47271  * necessary, inserting a new cache entry if none exists.
47272  */
47273 
47274  DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
47275  (void *) h, (long) char_offset,
47276  (long) DUK_HSTRING_GET_CHARLEN(h),
47277  (long) DUK_HSTRING_GET_BYTELEN(h)));
47278 
47279  heap = thr->heap;
47280  sce = NULL;
47281  use_cache = (DUK_HSTRING_GET_CHARLEN(h) > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
47282 
47283  if (use_cache) {
47284 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
47285  DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
47286  for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
47287  duk_strcache *c = heap->strcache + i;
47288  DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
47289  (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
47290  }
47291 #endif
47292 
47293  for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
47294  duk_strcache *c = heap->strcache + i;
47295 
47296  if (c->h == h) {
47297  sce = c;
47298  break;
47299  }
47300  }
47301  }
47302 
47303  /*
47304  * Scan from shortest distance:
47305  * - start of string
47306  * - end of string
47307  * - cache entry (if exists)
47308  */
47309 
47310  DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
47311  dist_start = char_offset;
47312  dist_end = DUK_HSTRING_GET_CHARLEN(h) - char_offset;
47313  dist_sce = 0; DUK_UNREF(dist_sce); /* initialize for debug prints, needed if sce==NULL */
47314 
47315  p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
47316  p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
47317  p_found = NULL;
47318 
47319  if (sce) {
47320  if (char_offset >= sce->cidx) {
47321  dist_sce = char_offset - sce->cidx;
47322  if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
47323  DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
47324  "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
47325  "scan forwards from sce",
47326  (long) use_cache, (void *) (sce ? sce->h : NULL),
47327  (sce ? (long) sce->cidx : (long) -1),
47328  (sce ? (long) sce->bidx : (long) -1),
47329  (long) dist_start, (long) dist_end, (long) dist_sce));
47330 
47331  p_found = duk__scan_forwards(p_start + sce->bidx,
47332  p_end,
47333  dist_sce);
47334  goto scan_done;
47335  }
47336  } else {
47337  dist_sce = sce->cidx - char_offset;
47338  if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
47339  DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
47340  "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
47341  "scan backwards from sce",
47342  (long) use_cache, (void *) (sce ? sce->h : NULL),
47343  (sce ? (long) sce->cidx : (long) -1),
47344  (sce ? (long) sce->bidx : (long) -1),
47345  (long) dist_start, (long) dist_end, (long) dist_sce));
47346 
47347  p_found = duk__scan_backwards(p_start + sce->bidx,
47348  p_start,
47349  dist_sce);
47350  goto scan_done;
47351  }
47352  }
47353  }
47354 
47355  /* no sce, or sce scan not best */
47356 
47357  if (dist_start <= dist_end) {
47358  DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
47359  "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
47360  "scan forwards from string start",
47361  (long) use_cache, (void *) (sce ? sce->h : NULL),
47362  (sce ? (long) sce->cidx : (long) -1),
47363  (sce ? (long) sce->bidx : (long) -1),
47364  (long) dist_start, (long) dist_end, (long) dist_sce));
47365 
47366  p_found = duk__scan_forwards(p_start,
47367  p_end,
47368  dist_start);
47369  } else {
47370  DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
47371  "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
47372  "scan backwards from string end",
47373  (long) use_cache, (void *) (sce ? sce->h : NULL),
47374  (sce ? (long) sce->cidx : (long) -1),
47375  (sce ? (long) sce->bidx : (long) -1),
47376  (long) dist_start, (long) dist_end, (long) dist_sce));
47377 
47378  p_found = duk__scan_backwards(p_end,
47379  p_start,
47380  dist_end);
47381  }
47382 
47383  scan_done:
47384 
47385  if (!p_found) {
47386  /* Scan error: this shouldn't normally happen; it could happen if
47387  * string is not valid UTF-8 data, and clen/blen are not consistent
47388  * with the scanning algorithm.
47389  */
47390  goto error;
47391  }
47392 
47393  DUK_ASSERT(p_found >= p_start);
47394  DUK_ASSERT(p_found <= p_end); /* may be equal */
47395  byte_offset = (duk_uint32_t) (p_found - p_start);
47396 
47397  DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
47398  (void *) h, (long) char_offset, (long) byte_offset));
47399 
47400  /*
47401  * Update cache entry (allocating if necessary), and move the
47402  * cache entry to the first place (in an "LRU" policy).
47403  */
47404 
47405  if (use_cache) {
47406  /* update entry, allocating if necessary */
47407  if (!sce) {
47408  sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1; /* take last entry */
47409  sce->h = h;
47410  }
47411  DUK_ASSERT(sce != NULL);
47412  sce->bidx = (duk_uint32_t) (p_found - p_start);
47413  sce->cidx = (duk_uint32_t) char_offset;
47414 
47415  /* LRU: move our entry to first */
47416  if (sce > &heap->strcache[0]) {
47417  /*
47418  * A C
47419  * B A
47420  * C <- sce ==> B
47421  * D D
47422  */
47423  duk_strcache tmp;
47424 
47425  tmp = *sce;
47426  DUK_MEMMOVE((void *) (&heap->strcache[1]),
47427  (const void *) (&heap->strcache[0]),
47428  (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
47429  heap->strcache[0] = tmp;
47430 
47431  /* 'sce' points to the wrong entry here, but is no longer used */
47432  }
47433 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
47434  DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
47435  for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
47436  duk_strcache *c = heap->strcache + i;
47437  DUK_DDD(DUK_DDDPRINT(" [%ld] -> h=%p, cidx=%ld, bidx=%ld",
47438  (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
47439  }
47440 #endif
47441  }
47442 
47443  return byte_offset;
47444 
47445  error:
47446  DUK_ERROR_INTERNAL(thr);
47447  return 0;
47448 }
47449 /*
47450  * Heap stringtable handling, string interning.
47451  */
47452 
47453 /* #include duk_internal.h -> already included */
47454 
47455 #if defined(DUK_USE_STRTAB_PROBE)
47456 #define DUK__HASH_INITIAL(hash,h_size) DUK_STRTAB_HASH_INITIAL((hash),(h_size))
47457 #define DUK__HASH_PROBE_STEP(hash) DUK_STRTAB_HASH_PROBE_STEP((hash))
47458 #define DUK__DELETED_MARKER(heap) DUK_STRTAB_DELETED_MARKER((heap))
47459 #endif
47460 
47461 #define DUK__PREVENT_MS_SIDE_EFFECTS(heap) do { \
47462  (heap)->mark_and_sweep_base_flags |= \
47463  DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive string table call */ \
47464  DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
47465  DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ \
47466  } while (0)
47467 
47468 /*
47469  * Create a hstring and insert into the heap. The created object
47470  * is directly garbage collectable with reference count zero.
47471  *
47472  * The caller must place the interned string into the stringtable
47473  * immediately (without chance of a longjmp); otherwise the string
47474  * is lost.
47475  */
47476 
47477 DUK_LOCAL
47478 duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
47479  const duk_uint8_t *str,
47480  duk_uint32_t blen,
47481  duk_uint32_t strhash,
47482  const duk_uint8_t *extdata) {
47483  duk_hstring *res = NULL;
47484  duk_uint8_t *data;
47485  duk_size_t alloc_size;
47486 #if !defined(DUK_USE_HSTRING_ARRIDX)
47487  duk_uarridx_t dummy;
47488 #endif
47489  duk_uint32_t clen;
47490 
47491 #if defined(DUK_USE_STRLEN16)
47492  /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
47493  if (blen > 0xffffUL) {
47494  DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
47495  return NULL;
47496  }
47497 #endif
47498 
47499  if (extdata) {
47500  alloc_size = (duk_size_t) sizeof(duk_hstring_external);
47501  res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
47502  if (!res) {
47503  goto alloc_error;
47504  }
47505  DUK_MEMZERO(res, sizeof(duk_hstring_external));
47506 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47507  DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
47508 #endif
47509  DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
47510 
47511  ((duk_hstring_external *) res)->extdata = extdata;
47512  } else {
47513  /* NUL terminate for convenient C access */
47514  alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
47515  res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
47516  if (!res) {
47517  goto alloc_error;
47518  }
47519  DUK_MEMZERO(res, sizeof(duk_hstring));
47520 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47521  DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
47522 #endif
47523  DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
47524 
47525  data = (duk_uint8_t *) (res + 1);
47526  DUK_MEMCPY(data, str, blen);
47527  data[blen] = (duk_uint8_t) 0;
47528  }
47529 
47530  DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
47531 #if defined(DUK_USE_HSTRING_ARRIDX)
47532  if (duk_js_to_arrayindex_raw_string(str, blen, &res->arridx)) {
47533 #else
47534  if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
47535 #endif
47536  DUK_HSTRING_SET_ARRIDX(res);
47537  }
47538 
47539  /* All strings beginning with specific (invalid UTF-8) byte prefixes
47540  * are treated as symbols.
47541  */
47542  DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(res));
47543  DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(res));
47544  if (blen > 0) {
47545  if (str[0] == 0xffU) {
47546  DUK_HSTRING_SET_SYMBOL(res);
47547  DUK_HSTRING_SET_HIDDEN(res);
47548  } else if ((str[0] & 0xc0U) == 0x80U) {
47549  DUK_HSTRING_SET_SYMBOL(res);
47550  }
47551  }
47552 
47553  DUK_HSTRING_SET_HASH(res, strhash);
47554  DUK_HSTRING_SET_BYTELEN(res, blen);
47555 
47556  clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
47557  DUK_ASSERT(clen <= blen);
47558 #if defined(DUK_USE_HSTRING_CLEN)
47559  DUK_HSTRING_SET_CHARLEN(res, clen);
47560 #endif
47561 
47562  /* Using an explicit 'ASCII' flag has larger footprint (one call site
47563  * only) but is quite useful for the case when there's no explicit
47564  * 'clen' in duk_hstring.
47565  */
47566  DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
47567  if (clen == blen) {
47568  DUK_HSTRING_SET_ASCII(res);
47569  }
47570 
47571  DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
47572  (unsigned long) DUK_HSTRING_GET_HASH(res),
47573  (long) DUK_HSTRING_GET_BYTELEN(res),
47574  (long) DUK_HSTRING_GET_CHARLEN(res),
47575  (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
47576  (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
47577 
47578  return res;
47579 
47580  alloc_error:
47581  DUK_FREE(heap, res);
47582  return NULL;
47583 }
47584 
47585 /*
47586  * String table algorithm: fixed size string table with array chaining
47587  *
47588  * The top level string table has a fixed size, with each slot holding
47589  * either NULL, string pointer, or pointer to a separately allocated
47590  * string pointer list.
47591  *
47592  * This is good for low memory environments using a pool allocator: the
47593  * top level allocation has a fixed size and the pointer lists have quite
47594  * small allocation size, which further matches the typical pool sizes
47595  * needed by objects, strings, property tables, etc.
47596  */
47597 
47598 #if defined(DUK_USE_STRTAB_CHAIN)
47599 
47600 #if defined(DUK_USE_HEAPPTR16)
47601 DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
47602  duk_small_uint_t slotidx;
47603  duk_strtab_entry *e;
47604  duk_uint16_t *lst;
47605  duk_uint16_t *new_lst;
47606  duk_size_t i, n;
47607  duk_uint16_t null16 = heap->heapptr_null16;
47608  duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47609 
47610  DUK_ASSERT(heap != NULL);
47611  DUK_ASSERT(h != NULL);
47612 
47613  slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
47614  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47615 
47616  e = heap->strtable + slotidx;
47617  if (e->listlen == 0) {
47618  if (e->u.str16 == null16) {
47619  e->u.str16 = h16;
47620  } else {
47621  /* Now two entries in the same slot, alloc list */
47622  lst = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * 2);
47623  if (lst == NULL) {
47624  return 1; /* fail */
47625  }
47626  lst[0] = e->u.str16;
47627  lst[1] = h16;
47628  e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) lst);
47629  e->listlen = 2;
47630  }
47631  } else {
47632  DUK_ASSERT(e->u.strlist16 != null16);
47633  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
47634  DUK_ASSERT(lst != NULL);
47635  for (i = 0, n = e->listlen; i < n; i++) {
47636  if (lst[i] == null16) {
47637  lst[i] = h16;
47638  return 0;
47639  }
47640  }
47641 
47642  if (e->listlen + 1 == 0) {
47643  /* Overflow, relevant mainly when listlen is 16 bits. */
47644  return 1; /* fail */
47645  }
47646 
47647  new_lst = (duk_uint16_t *) DUK_REALLOC(heap, lst, sizeof(duk_uint16_t) * (e->listlen + 1));
47648  if (new_lst == NULL) {
47649  return 1; /* fail */
47650  }
47651  new_lst[e->listlen++] = h16;
47652  e->u.strlist16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) new_lst);
47653  }
47654  return 0;
47655 }
47656 #else /* DUK_USE_HEAPPTR16 */
47657 DUK_LOCAL duk_bool_t duk__insert_hstring_chain(duk_heap *heap, duk_hstring *h) {
47658  duk_small_uint_t slotidx;
47659  duk_strtab_entry *e;
47660  duk_hstring **lst;
47661  duk_hstring **new_lst;
47662  duk_size_t i, n;
47663 
47664  DUK_ASSERT(heap != NULL);
47665  DUK_ASSERT(h != NULL);
47666 
47667  slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
47668  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47669 
47670  e = heap->strtable + slotidx;
47671  if (e->listlen == 0) {
47672  if (e->u.str == NULL) {
47673  e->u.str = h;
47674  } else {
47675  /* Now two entries in the same slot, alloc list */
47676  lst = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * 2);
47677  if (lst == NULL) {
47678  return 1; /* fail */
47679  }
47680  lst[0] = e->u.str;
47681  lst[1] = h;
47682  e->u.strlist = lst;
47683  e->listlen = 2;
47684  }
47685  } else {
47686  DUK_ASSERT(e->u.strlist != NULL);
47687  lst = e->u.strlist;
47688  for (i = 0, n = e->listlen; i < n; i++) {
47689  if (lst[i] == NULL) {
47690  lst[i] = h;
47691  return 0;
47692  }
47693  }
47694 
47695  if (e->listlen + 1 == 0) {
47696  /* Overflow, relevant mainly when listlen is 16 bits. */
47697  return 1; /* fail */
47698  }
47699 
47700  new_lst = (duk_hstring **) DUK_REALLOC(heap, e->u.strlist, sizeof(duk_hstring *) * (e->listlen + 1));
47701  if (new_lst == NULL) {
47702  return 1; /* fail */
47703  }
47704  new_lst[e->listlen++] = h;
47705  e->u.strlist = new_lst;
47706  }
47707  return 0;
47708 }
47709 #endif /* DUK_USE_HEAPPTR16 */
47710 
47711 #if defined(DUK_USE_HEAPPTR16)
47712 DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
47713  duk_small_uint_t slotidx;
47714  duk_strtab_entry *e;
47715  duk_uint16_t *lst;
47716  duk_size_t i, n;
47717  duk_uint16_t null16 = heap->heapptr_null16;
47718 
47719  DUK_ASSERT(heap != NULL);
47720 
47721  slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
47722  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47723 
47724  e = heap->strtable + slotidx;
47725  if (e->listlen == 0) {
47726  if (e->u.str16 != null16) {
47727  duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
47728  DUK_ASSERT(h != NULL);
47729  if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
47730  DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
47731  return h;
47732  }
47733  }
47734  } else {
47735  DUK_ASSERT(e->u.strlist16 != null16);
47736  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
47737  DUK_ASSERT(lst != NULL);
47738  for (i = 0, n = e->listlen; i < n; i++) {
47739  if (lst[i] != null16) {
47740  duk_hstring *h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[i]);
47741  DUK_ASSERT(h != NULL);
47742  if (DUK_HSTRING_GET_BYTELEN(h) == blen &&
47743  DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
47744  return h;
47745  }
47746  }
47747  }
47748  }
47749 
47750  return NULL;
47751 }
47752 #else /* DUK_USE_HEAPPTR16 */
47753 DUK_LOCAL duk_hstring *duk__find_matching_string_chain(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
47754  duk_small_uint_t slotidx;
47755  duk_strtab_entry *e;
47756  duk_hstring **lst;
47757  duk_size_t i, n;
47758 
47759  DUK_ASSERT(heap != NULL);
47760 
47761  slotidx = strhash % DUK_STRTAB_CHAIN_SIZE;
47762  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47763 
47764  e = heap->strtable + slotidx;
47765  if (e->listlen == 0) {
47766  if (e->u.str != NULL &&
47767  DUK_HSTRING_GET_BYTELEN(e->u.str) == blen &&
47768  DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e->u.str), (size_t) blen) == 0) {
47769  return e->u.str;
47770  }
47771  } else {
47772  DUK_ASSERT(e->u.strlist != NULL);
47773  lst = e->u.strlist;
47774  for (i = 0, n = e->listlen; i < n; i++) {
47775  if (lst[i] != NULL &&
47776  DUK_HSTRING_GET_BYTELEN(lst[i]) == blen &&
47777  DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(lst[i]), (size_t) blen) == 0) {
47778  return lst[i];
47779  }
47780  }
47781  }
47782 
47783  return NULL;
47784 }
47785 #endif /* DUK_USE_HEAPPTR16 */
47786 
47787 #if defined(DUK_USE_HEAPPTR16)
47788 DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
47789  duk_small_uint_t slotidx;
47790  duk_strtab_entry *e;
47791  duk_uint16_t *lst;
47792  duk_size_t i, n;
47793  duk_uint16_t h16;
47794  duk_uint16_t null16 = heap->heapptr_null16;
47795 
47796  DUK_ASSERT(heap != NULL);
47797  DUK_ASSERT(h != NULL);
47798 
47799  slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
47800  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47801 
47802  DUK_ASSERT(h != NULL);
47803  h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47804 
47805  e = heap->strtable + slotidx;
47806  if (e->listlen == 0) {
47807  if (e->u.str16 == h16) {
47808  e->u.str16 = null16;
47809  return;
47810  }
47811  } else {
47812  DUK_ASSERT(e->u.strlist16 != null16);
47813  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
47814  DUK_ASSERT(lst != NULL);
47815  for (i = 0, n = e->listlen; i < n; i++) {
47816  if (lst[i] == h16) {
47817  lst[i] = null16;
47818  return;
47819  }
47820  }
47821  }
47822 
47823  DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
47824  DUK_UNREACHABLE();
47825  return;
47826 }
47827 #else /* DUK_USE_HEAPPTR16 */
47828 DUK_LOCAL void duk__remove_matching_hstring_chain(duk_heap *heap, duk_hstring *h) {
47829  duk_small_uint_t slotidx;
47830  duk_strtab_entry *e;
47831  duk_hstring **lst;
47832  duk_size_t i, n;
47833 
47834  DUK_ASSERT(heap != NULL);
47835  DUK_ASSERT(h != NULL);
47836 
47837  slotidx = DUK_HSTRING_GET_HASH(h) % DUK_STRTAB_CHAIN_SIZE;
47838  DUK_ASSERT(slotidx < DUK_STRTAB_CHAIN_SIZE);
47839 
47840  e = heap->strtable + slotidx;
47841  if (e->listlen == 0) {
47842  DUK_ASSERT(h != NULL);
47843  if (e->u.str == h) {
47844  e->u.str = NULL;
47845  return;
47846  }
47847  } else {
47848  DUK_ASSERT(e->u.strlist != NULL);
47849  lst = e->u.strlist;
47850  for (i = 0, n = e->listlen; i < n; i++) {
47851  DUK_ASSERT(h != NULL);
47852  if (lst[i] == h) {
47853  lst[i] = NULL;
47854  return;
47855  }
47856  }
47857  }
47858 
47859  DUK_D(DUK_DPRINT("failed to find string that should be in stringtable"));
47860  DUK_UNREACHABLE();
47861  return;
47862 }
47863 #endif /* DUK_USE_HEAPPTR16 */
47864 
47865 #if defined(DUK_USE_DEBUG)
47866 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
47867  duk_strtab_entry *e;
47868  duk_small_uint_t i;
47869  duk_size_t j, n, used;
47870 #if defined(DUK_USE_HEAPPTR16)
47871  duk_uint16_t *lst;
47872  duk_uint16_t null16 = heap->heapptr_null16;
47873 #else
47874  duk_hstring **lst;
47875 #endif
47876 
47877  DUK_ASSERT(heap != NULL);
47878 
47879  for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
47880  e = heap->strtable + i;
47881 
47882  if (e->listlen == 0) {
47883 #if defined(DUK_USE_HEAPPTR16)
47884  DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str16 != null16 ? 1 : 0)));
47885 #else
47886  DUK_DD(DUK_DDPRINT("[%03d] -> plain %d", (int) i, (int) (e->u.str ? 1 : 0)));
47887 #endif
47888  } else {
47889  used = 0;
47890 #if defined(DUK_USE_HEAPPTR16)
47891  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
47892 #else
47893  lst = e->u.strlist;
47894 #endif
47895  DUK_ASSERT(lst != NULL);
47896  for (j = 0, n = e->listlen; j < n; j++) {
47897 #if defined(DUK_USE_HEAPPTR16)
47898  if (lst[j] != null16) {
47899 #else
47900  if (lst[j] != NULL) {
47901 #endif
47902  used++;
47903  }
47904  }
47905  DUK_DD(DUK_DDPRINT("[%03d] -> array %d/%d", (int) i, (int) used, (int) e->listlen));
47906  }
47907  }
47908 }
47909 #endif /* DUK_USE_DEBUG */
47910 
47911 #endif /* DUK_USE_STRTAB_CHAIN */
47912 
47913 /*
47914  * String table algorithm: closed hashing with a probe sequence
47915  *
47916  * This is the default algorithm and works fine for environments with
47917  * minimal memory constraints.
47918  */
47919 
47920 #if defined(DUK_USE_STRTAB_PROBE)
47921 
47922 /* Count actually used (non-NULL, non-DELETED) entries. */
47923 DUK_LOCAL duk_int_t duk__count_used_probe(duk_heap *heap) {
47924  duk_int_t res = 0;
47925  duk_uint_fast32_t i, n;
47926 #if defined(DUK_USE_HEAPPTR16)
47927  duk_uint16_t null16 = heap->heapptr_null16;
47928  duk_uint16_t deleted16 = heap->heapptr_deleted16;
47929 #endif
47930 
47931  n = (duk_uint_fast32_t) heap->st_size;
47932  for (i = 0; i < n; i++) {
47933 #if defined(DUK_USE_HEAPPTR16)
47934  if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
47935 #else
47936  if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
47937 #endif
47938  res++;
47939  }
47940  }
47941  return res;
47942 }
47943 
47944 #if defined(DUK_USE_HEAPPTR16)
47945 DUK_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) {
47946 #else
47947 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) {
47948 #endif
47949  duk_uint32_t i;
47950  duk_uint32_t step;
47951 #if defined(DUK_USE_HEAPPTR16)
47952  duk_uint16_t null16 = heap->heapptr_null16;
47953  duk_uint16_t deleted16 = heap->heapptr_deleted16;
47954 #endif
47955 
47956  DUK_ASSERT(size > 0);
47957 
47958  i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(h), size);
47959  step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(h));
47960  for (;;) {
47961 #if defined(DUK_USE_HEAPPTR16)
47962  duk_uint16_t e16 = entries16[i];
47963 #else
47964  duk_hstring *e = entries[i];
47965 #endif
47966 
47967 #if defined(DUK_USE_HEAPPTR16)
47968  /* XXX: could check for e16 == 0 because NULL is guaranteed to
47969  * encode to zero.
47970  */
47971  if (e16 == null16) {
47972 #else
47973  if (e == NULL) {
47974 #endif
47975  DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
47976 #if defined(DUK_USE_HEAPPTR16)
47977  entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47978 #else
47979  entries[i] = h;
47980 #endif
47981  (*p_used)++;
47982  break;
47983 #if defined(DUK_USE_HEAPPTR16)
47984  } else if (e16 == deleted16) {
47985 #else
47986  } else if (e == DUK__DELETED_MARKER(heap)) {
47987 #endif
47988  /* st_used remains the same, DELETED is counted as used */
47989  DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
47990 #if defined(DUK_USE_HEAPPTR16)
47991  entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47992 #else
47993  entries[i] = h;
47994 #endif
47995  break;
47996  }
47997  DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
47998  i = (i + step) % size;
47999 
48000  /* looping should never happen */
48001  DUK_ASSERT(i != DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(h), size));
48002  }
48003 }
48004 
48005 #if defined(DUK_USE_HEAPPTR16)
48006 DUK_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) {
48007 #else
48008 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) {
48009 #endif
48010  duk_uint32_t i;
48011  duk_uint32_t step;
48012 
48013  DUK_ASSERT(size > 0);
48014 
48015  i = DUK__HASH_INITIAL(strhash, size);
48016  step = DUK__HASH_PROBE_STEP(strhash);
48017  for (;;) {
48018  duk_hstring *e;
48019 #if defined(DUK_USE_HEAPPTR16)
48020  e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
48021 #else
48022  e = entries[i];
48023 #endif
48024 
48025  if (!e) {
48026  return NULL;
48027  }
48028  if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
48029  if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
48030  DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
48031  (long) i, (long) step, (long) size));
48032  return e;
48033  }
48034  }
48035  DUK_DDD(DUK_DDDPRINT("find matching miss: %ld (step %ld, size %ld)",
48036  (long) i, (long) step, (long) size));
48037  i = (i + step) % size;
48038 
48039  /* looping should never happen */
48040  DUK_ASSERT(i != DUK__HASH_INITIAL(strhash, size));
48041  }
48042  DUK_UNREACHABLE();
48043 }
48044 
48045 #if defined(DUK_USE_HEAPPTR16)
48046 DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_uint16_t *entries16, duk_uint32_t size, duk_hstring *h) {
48047 #else
48048 DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h) {
48049 #endif
48050  duk_uint32_t i;
48051  duk_uint32_t step;
48052  duk_uint32_t hash;
48053 #if defined(DUK_USE_HEAPPTR16)
48054  duk_uint16_t null16 = heap->heapptr_null16;
48055  duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
48056 #endif
48057 
48058  DUK_ASSERT(size > 0);
48059 
48060  hash = DUK_HSTRING_GET_HASH(h);
48061  i = DUK__HASH_INITIAL(hash, size);
48062  step = DUK__HASH_PROBE_STEP(hash);
48063  for (;;) {
48064 #if defined(DUK_USE_HEAPPTR16)
48065  duk_uint16_t e16 = entries16[i];
48066 #else
48067  duk_hstring *e = entries[i];
48068 #endif
48069 
48070 #if defined(DUK_USE_HEAPPTR16)
48071  if (e16 == null16) {
48072 #else
48073  if (!e) {
48074 #endif
48075  DUK_UNREACHABLE();
48076  break;
48077  }
48078 #if defined(DUK_USE_HEAPPTR16)
48079  if (e16 == h16) {
48080 #else
48081  if (e == h) {
48082 #endif
48083  /* st_used remains the same, DELETED is counted as used */
48084  DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
48085 #if defined(DUK_USE_HEAPPTR16)
48086  entries16[i] = heap->heapptr_deleted16;
48087 #else
48088  entries[i] = DUK__DELETED_MARKER(heap);
48089 #endif
48090  break;
48091  }
48092 
48093  DUK_DDD(DUK_DDDPRINT("free matching miss: %ld", (long) i));
48094  i = (i + step) % size;
48095 
48096  /* looping should never happen */
48097  DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
48098  }
48099 }
48100 
48101 DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size) {
48102 #if defined(DUK_USE_DEBUG)
48103  duk_uint32_t old_used = heap->st_used;
48104 #endif
48105  duk_uint32_t old_size = heap->st_size;
48106 #if defined(DUK_USE_HEAPPTR16)
48107  duk_uint16_t *old_entries = heap->strtable16;
48108  duk_uint16_t *new_entries = NULL;
48109 #else
48110  duk_hstring **old_entries = heap->strtable;
48111  duk_hstring **new_entries = NULL;
48112 #endif
48113  duk_uint32_t new_used = 0;
48114  duk_uint32_t i;
48115 
48116 #if defined(DUK_USE_DEBUG)
48117  DUK_UNREF(old_used); /* unused with some debug level combinations */
48118 #endif
48119 
48120 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
48121  DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
48122  (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
48123  (long) (((double) old_used) / ((double) old_size) * 100.0),
48124  (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
48125  (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
48126 #endif
48127 
48128  DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap)); /* required for rehash to succeed, equality not that useful */
48129  DUK_ASSERT(old_entries);
48130 
48131  /*
48132  * The attempt to allocate may cause a GC. Such a GC must not attempt to resize
48133  * the stringtable (though it can be swept); finalizer execution and object
48134  * compaction must also be postponed to avoid the pressure to add strings to the
48135  * string table. Call site must prevent these.
48136  */
48137 
48138  DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE);
48139  DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_FINALIZERS);
48140  DUK_ASSERT(heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION);
48141 
48142 #if defined(DUK_USE_HEAPPTR16)
48143  new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
48144 #else
48145  new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
48146 #endif
48147 
48148  if (!new_entries) {
48149  goto resize_error;
48150  }
48151 
48152 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48153  for (i = 0; i < new_size; i++) {
48154 #if defined(DUK_USE_HEAPPTR16)
48155  new_entries[i] = heap->heapptr_null16;
48156 #else
48157  new_entries[i] = NULL;
48158 #endif
48159  }
48160 #else
48161 #if defined(DUK_USE_HEAPPTR16)
48162  /* Relies on NULL encoding to zero. */
48163  DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
48164 #else
48165  DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
48166 #endif
48167 #endif
48168 
48169  /* Because new_size > duk__count_used_probe(heap), guaranteed to work */
48170  for (i = 0; i < old_size; i++) {
48171  duk_hstring *e;
48172 
48173 #if defined(DUK_USE_HEAPPTR16)
48174  e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
48175 #else
48176  e = old_entries[i];
48177 #endif
48178  if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
48179  continue;
48180  }
48181  /* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
48182  duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
48183  }
48184 
48185 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
48186  DUK_DD(DUK_DDPRINT("resized stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
48187  (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
48188  (long) (((double) old_used) / ((double) old_size) * 100.0),
48189  (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) new_used,
48190  (long) (((double) new_used) / ((double) new_size) * 100.0)));
48191 #endif
48192 
48193 #if defined(DUK_USE_HEAPPTR16)
48194  DUK_FREE(heap, heap->strtable16);
48195  heap->strtable16 = new_entries;
48196 #else
48197  DUK_FREE(heap, heap->strtable);
48198  heap->strtable = new_entries;
48199 #endif
48200  heap->st_size = new_size;
48201  heap->st_used = new_used; /* may be less, since DELETED entries are NULLed by rehash */
48202 
48203  return 0; /* OK */
48204 
48205  resize_error:
48206  DUK_FREE(heap, new_entries);
48207  return 1; /* FAIL */
48208 }
48209 
48210 DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap) {
48211  duk_uint32_t new_size;
48212  duk_bool_t ret;
48213 
48214  new_size = (duk_uint32_t) duk__count_used_probe(heap);
48215  if (new_size >= 0x80000000UL) {
48216  new_size = DUK_STRTAB_HIGHEST_32BIT_PRIME;
48217  } else {
48218  new_size = duk_util_get_hash_prime(DUK_STRTAB_GROW_ST_SIZE(new_size));
48219  new_size = duk_util_get_hash_prime(new_size);
48220  }
48221  DUK_ASSERT(new_size > 0);
48222 
48223  /* rehash even if old and new sizes are the same to get rid of
48224  * DELETED entries.
48225  */
48226 
48227  ret = duk__resize_strtab_raw_probe(heap, new_size);
48228 
48229  return ret;
48230 }
48231 
48232 DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used) {
48233  duk_uint32_t new_free;
48234  duk_uint32_t tmp1;
48235  duk_uint32_t tmp2;
48236 
48237  DUK_ASSERT(new_used <= heap->st_size); /* grow by at most one */
48238  new_free = heap->st_size - new_used; /* unsigned intentionally */
48239 
48240  /* new_free / size <= 1 / DIV <=> new_free <= size / DIV */
48241  /* new_used / size <= 1 / DIV <=> new_used <= size / DIV */
48242 
48243  tmp1 = heap->st_size / DUK_STRTAB_MIN_FREE_DIVISOR;
48244  tmp2 = heap->st_size / DUK_STRTAB_MIN_USED_DIVISOR;
48245 
48246  if (new_free <= tmp1 || new_used <= tmp2) {
48247  /* load factor too low or high, count actually used entries and resize */
48248  return duk__resize_strtab_probe(heap);
48249  } else {
48250  return 0; /* OK */
48251  }
48252 }
48253 
48254 #if defined(DUK_USE_DEBUG)
48255 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap) {
48256  duk_uint32_t i;
48257  duk_hstring *h;
48258 
48259  DUK_ASSERT(heap != NULL);
48260 #if defined(DUK_USE_HEAPPTR16)
48261  DUK_ASSERT(heap->strtable16 != NULL);
48262 #else
48263  DUK_ASSERT(heap->strtable != NULL);
48264 #endif
48265  DUK_UNREF(h);
48266 
48267  for (i = 0; i < heap->st_size; i++) {
48268 #if defined(DUK_USE_HEAPPTR16)
48269  h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->strtable16[i]);
48270 #else
48271  h = heap->strtable[i];
48272 #endif
48273 
48274  DUK_DD(DUK_DDPRINT("[%03d] -> %p", (int) i, (void *) h));
48275  }
48276 }
48277 #endif /* DUK_USE_DEBUG */
48278 
48279 #endif /* DUK_USE_STRTAB_PROBE */
48280 
48281 /*
48282  * Raw intern and lookup
48283  */
48284 
48285 DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
48286  duk_hstring *res;
48287  const duk_uint8_t *extdata;
48288  duk_small_uint_t prev_mark_and_sweep_base_flags;
48289 
48290  /* Prevent any side effects on the string table and the caller provided
48291  * str/blen arguments while interning is in progress. For example, if
48292  * the caller provided str/blen from a dynamic buffer, a finalizer might
48293  * resize that dynamic buffer, invalidating the call arguments.
48294  */
48295  DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
48296  prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
48297  DUK__PREVENT_MS_SIDE_EFFECTS(heap);
48298 
48299 #if defined(DUK_USE_STRTAB_PROBE)
48300  if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
48301  goto failed;
48302  }
48303 #endif
48304 
48305 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
48306  extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
48307 #else
48308  extdata = (const duk_uint8_t *) NULL;
48309 #endif
48310  res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
48311  if (!res) {
48312  goto failed;
48313  }
48314 
48315 #if defined(DUK_USE_STRTAB_CHAIN)
48316  if (duk__insert_hstring_chain(heap, res)) {
48317  /* failed */
48318  DUK_FREE(heap, res);
48319  goto failed;
48320  }
48321 #elif defined(DUK_USE_STRTAB_PROBE)
48322  /* guaranteed to succeed */
48323  duk__insert_hstring_probe(heap,
48324 #if defined(DUK_USE_HEAPPTR16)
48325  heap->strtable16,
48326 #else
48327  heap->strtable,
48328 #endif
48329  heap->st_size,
48330  &heap->st_used,
48331  res);
48332 #else
48333 #error internal error, invalid strtab options
48334 #endif
48335 
48336  /* Note: hstring is in heap but has refcount zero and is not strongly reachable.
48337  * Caller should increase refcount and make the hstring reachable before any
48338  * operations which require allocation (and possible gc).
48339  */
48340 
48341  done:
48342  heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48343  return res;
48344 
48345  failed:
48346  res = NULL;
48347  goto done;
48348 }
48349 
48350 DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) {
48351  duk_hstring *res;
48352 
48353  DUK_ASSERT(out_strhash);
48354 
48355  *out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
48356 
48357 #if defined(DUK_USE_ROM_STRINGS)
48358  {
48359  duk_small_uint_t i;
48360  /* XXX: This is VERY inefficient now, and should be e.g. a
48361  * binary search or perfect hash, to be fixed.
48362  */
48363  for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) {
48364  duk_hstring *romstr;
48365  romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]);
48366  if (blen == DUK_HSTRING_GET_BYTELEN(romstr) &&
48367  DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) {
48368  DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
48369  romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr)));
48370  DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr));
48371  *out_strhash = DUK_HSTRING_GET_HASH(romstr);
48372  return romstr;
48373  }
48374  }
48375  }
48376 #endif /* DUK_USE_ROM_STRINGS */
48377 
48378 #if defined(DUK_USE_STRTAB_CHAIN)
48379  res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
48380 #elif defined(DUK_USE_STRTAB_PROBE)
48381  res = duk__find_matching_string_probe(heap,
48382 #if defined(DUK_USE_HEAPPTR16)
48383  heap->strtable16,
48384 #else
48385  heap->strtable,
48386 #endif
48387  heap->st_size,
48388  str,
48389  blen,
48390  *out_strhash);
48391 #else
48392 #error internal error, invalid strtab options
48393 #endif
48394 
48395  return res;
48396 }
48397 
48398 /*
48399  * Exposed calls
48400  */
48401 
48402 #if 0 /*unused*/
48403 DUK_INTERNAL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
48404  duk_uint32_t strhash; /* dummy */
48405  return duk__do_lookup(heap, str, blen, &strhash);
48406 }
48407 #endif
48408 
48409 DUK_INTERNAL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
48410  duk_hstring *res;
48411  duk_uint32_t strhash;
48412 
48413  /* caller is responsible for ensuring this */
48414  DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);
48415 
48416  res = duk__do_lookup(heap, str, blen, &strhash);
48417  if (res) {
48418  return res;
48419  }
48420 
48421  res = duk__do_intern(heap, str, blen, strhash);
48422  return res; /* may be NULL */
48423 }
48424 
48425 DUK_INTERNAL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
48426  duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
48427  if (!res) {
48428  DUK_ERROR_ALLOC_FAILED(thr);
48429  }
48430  return res;
48431 }
48432 
48433 #if 0 /*unused*/
48434 DUK_INTERNAL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val) {
48435  char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
48436  DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
48437  buf[sizeof(buf) - 1] = (char) 0;
48438  DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
48439  return duk_heap_string_lookup(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
48440 }
48441 #endif
48442 
48443 DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val) {
48444  char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
48445  DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
48446  buf[sizeof(buf) - 1] = (char) 0;
48447  DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
48448  return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
48449 }
48450 
48451 DUK_INTERNAL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
48452  duk_hstring *res = duk_heap_string_intern_u32(thr->heap, val);
48453  if (!res) {
48454  DUK_ERROR_ALLOC_FAILED(thr);
48455  }
48456  return res;
48457 }
48458 
48459 /* find and remove string from stringtable; caller must free the string itself */
48460 #if defined(DUK_USE_REFERENCE_COUNTING)
48461 DUK_INTERNAL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h) {
48462  DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
48463 
48464 #if defined(DUK_USE_STRTAB_CHAIN)
48465  duk__remove_matching_hstring_chain(heap, h);
48466 #elif defined(DUK_USE_STRTAB_PROBE)
48467  duk__remove_matching_hstring_probe(heap,
48468 #if defined(DUK_USE_HEAPPTR16)
48469  heap->strtable16,
48470 #else
48471  heap->strtable,
48472 #endif
48473  heap->st_size,
48474  h);
48475 #else
48476 #error internal error, invalid strtab options
48477 #endif
48478 }
48479 #endif
48480 
48481 #if defined(DUK_USE_MS_STRINGTABLE_RESIZE)
48482 DUK_INTERNAL void duk_heap_force_strtab_resize(duk_heap *heap) {
48483  duk_small_uint_t prev_mark_and_sweep_base_flags;
48484  /* Force a resize so that DELETED entries are eliminated.
48485  * Another option would be duk__recheck_strtab_size_probe();
48486  * but since that happens on every intern anyway, this whole
48487  * check can now be disabled.
48488  */
48489 
48490  DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0);
48491  prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
48492  DUK__PREVENT_MS_SIDE_EFFECTS(heap);
48493 
48494 #if defined(DUK_USE_STRTAB_CHAIN)
48495  DUK_UNREF(heap);
48496 #elif defined(DUK_USE_STRTAB_PROBE)
48497  (void) duk__resize_strtab_probe(heap);
48498 #endif
48499 
48500  heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
48501 }
48502 #endif
48503 
48504 #if defined(DUK_USE_STRTAB_CHAIN)
48505 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
48506  /* Free strings in the stringtable and any allocations needed
48507  * by the stringtable itself.
48508  */
48509  duk_uint_fast32_t i, j;
48510  duk_strtab_entry *e;
48511 #if defined(DUK_USE_HEAPPTR16)
48512  duk_uint16_t *lst;
48513  duk_uint16_t null16 = heap->heapptr_null16;
48514 #else
48515  duk_hstring **lst;
48516 #endif
48517  duk_hstring *h;
48518 
48519  for (i = 0; i < DUK_STRTAB_CHAIN_SIZE; i++) {
48520  e = heap->strtable + i;
48521  if (e->listlen > 0) {
48522 #if defined(DUK_USE_HEAPPTR16)
48523  lst = (duk_uint16_t *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.strlist16);
48524 #else
48525  lst = e->u.strlist;
48526 #endif
48527  DUK_ASSERT(lst != NULL);
48528 
48529  for (j = 0; j < e->listlen; j++) {
48530 #if defined(DUK_USE_HEAPPTR16)
48531  h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, lst[j]);
48532  lst[j] = null16;
48533 #else
48534  h = lst[j];
48535  lst[j] = NULL;
48536 #endif
48537  /* strings may have inner refs (extdata) in some cases */
48538  if (h != NULL) {
48539  duk_free_hstring(heap, h);
48540  }
48541  }
48542 #if defined(DUK_USE_HEAPPTR16)
48543  e->u.strlist16 = null16;
48544 #else
48545  e->u.strlist = NULL;
48546 #endif
48547  DUK_FREE(heap, lst);
48548  } else {
48549 #if defined(DUK_USE_HEAPPTR16)
48550  h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, e->u.str16);
48551  e->u.str16 = null16;
48552 #else
48553  h = e->u.str;
48554  e->u.str = NULL;
48555 #endif
48556  if (h != NULL) {
48557  duk_free_hstring(heap, h);
48558  }
48559  }
48560  e->listlen = 0;
48561  }
48562 }
48563 #endif /* DUK_USE_STRTAB_CHAIN */
48564 
48565 #if defined(DUK_USE_STRTAB_PROBE)
48566 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap) {
48567  duk_uint_fast32_t i;
48568  duk_hstring *h;
48569 
48570 #if defined(DUK_USE_HEAPPTR16)
48571  if (heap->strtable16) {
48572 #else
48573  if (heap->strtable) {
48574 #endif
48575  for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
48576 #if defined(DUK_USE_HEAPPTR16)
48577  h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
48578 #else
48579  h = heap->strtable[i];
48580 #endif
48581  if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
48582  continue;
48583  }
48584  DUK_ASSERT(h != NULL);
48585 
48586  /* strings may have inner refs (extdata) in some cases */
48587  duk_free_hstring(heap, h);
48588 #if 0 /* not strictly necessary */
48589  heap->strtable[i] = NULL;
48590 #endif
48591  }
48592 #if defined(DUK_USE_HEAPPTR16)
48593  DUK_FREE(heap, heap->strtable16);
48594 #else
48595  DUK_FREE(heap, heap->strtable);
48596 #endif
48597 #if 0 /* not strictly necessary */
48598  heap->strtable = NULL;
48599 #endif
48600  }
48601 }
48602 #endif /* DUK_USE_STRTAB_PROBE */
48603 
48604 /* automatic undefs */
48605 #undef DUK__DELETED_MARKER
48606 #undef DUK__HASH_INITIAL
48607 #undef DUK__HASH_PROBE_STEP
48608 #undef DUK__PREVENT_MS_SIDE_EFFECTS
48609 /*
48610  * Hobject allocation.
48611  *
48612  * Provides primitive allocation functions for all object types (plain object,
48613  * compiled function, native function, thread). The object return is not yet
48614  * in "heap allocated" list and has a refcount of zero, so caller must careful.
48615  */
48616 
48617 /* #include duk_internal.h -> already included */
48618 
48619 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_hobject *obj, duk_uint_t hobject_flags) {
48620 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48621  DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
48622 #endif
48623 
48624  /* XXX: macro? sets both heaphdr and object flags */
48625  obj->hdr.h_flags = hobject_flags;
48626  DUK_HEAPHDR_SET_TYPE(&obj->hdr, DUK_HTYPE_OBJECT); /* also goes into flags */
48627 
48628 #if defined(DUK_USE_HEAPPTR16)
48629  /* Zero encoded pointer is required to match NULL */
48630  DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
48631 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
48632  DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
48633 #endif
48634 #endif
48635  DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
48636  DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
48637 
48638  /*
48639  * obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
48640  * with this properly. This is intentional: empty objects consume a minimum
48641  * amount of memory. Further, an initial allocation might fail and cause
48642  * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
48643  */
48644 }
48645 
48646 /*
48647  * Allocate an duk_hobject.
48648  *
48649  * The allocated object has no allocation for properties; the caller may
48650  * want to force a resize if a desired size is known.
48651  *
48652  * The allocated object has zero reference count and is not reachable.
48653  * The caller MUST make the object reachable and increase its reference
48654  * count before invoking any operation that might require memory allocation.
48655  */
48656 
48657 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48658  duk_hobject *res;
48659 
48660  DUK_ASSERT(heap != NULL);
48661 
48662  /* different memory layout, alloc size, and init */
48663  DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
48664  DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
48665  DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_THREAD) == 0);
48666 
48667  res = (duk_hobject *) DUK_ALLOC(heap, sizeof(duk_hobject));
48668  if (!res) {
48669  return NULL;
48670  }
48671  DUK_MEMZERO(res, sizeof(duk_hobject));
48672 
48673  duk__init_object_parts(heap, res, hobject_flags);
48674 
48675  return res;
48676 }
48677 
48678 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48679  duk_hcompfunc *res;
48680 
48681  res = (duk_hcompfunc *) DUK_ALLOC(heap, sizeof(duk_hcompfunc));
48682  if (!res) {
48683  return NULL;
48684  }
48685  DUK_MEMZERO(res, sizeof(duk_hcompfunc));
48686 
48687  duk__init_object_parts(heap, &res->obj, hobject_flags);
48688 
48689 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48690 #if defined(DUK_USE_HEAPPTR16)
48691  /* NULL pointer is required to encode to zero, so memset is enough. */
48692 #else
48693  res->data = NULL;
48694  res->funcs = NULL;
48695  res->bytecode = NULL;
48696 #endif
48697  res->lex_env = NULL;
48698  res->var_env = NULL;
48699 #endif
48700 
48701  return res;
48702 }
48703 
48704 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48705  duk_hnatfunc *res;
48706 
48707  res = (duk_hnatfunc *) DUK_ALLOC(heap, sizeof(duk_hnatfunc));
48708  if (!res) {
48709  return NULL;
48710  }
48711  DUK_MEMZERO(res, sizeof(duk_hnatfunc));
48712 
48713  duk__init_object_parts(heap, &res->obj, hobject_flags);
48714 
48715 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48716  res->func = NULL;
48717 #endif
48718 
48719  return res;
48720 }
48721 
48722 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
48723 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48724  duk_hbufobj *res;
48725 
48726  res = (duk_hbufobj *) DUK_ALLOC(heap, sizeof(duk_hbufobj));
48727  if (!res) {
48728  return NULL;
48729  }
48730  DUK_MEMZERO(res, sizeof(duk_hbufobj));
48731 
48732  duk__init_object_parts(heap, &res->obj, hobject_flags);
48733 
48734 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48735  res->buf = NULL;
48736  res->buf_prop = NULL;
48737 #endif
48738 
48739  DUK_ASSERT_HBUFOBJ_VALID(res);
48740  return res;
48741 }
48742 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
48743 
48744 /*
48745  * Allocate a new thread.
48746  *
48747  * Leaves the built-ins array uninitialized. The caller must either
48748  * initialize a new global context or share existing built-ins from
48749  * another thread.
48750  */
48751 
48752 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48753  duk_hthread *res;
48754 
48755  res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
48756  if (!res) {
48757  return NULL;
48758  }
48759  DUK_MEMZERO(res, sizeof(duk_hthread));
48760 
48761  duk__init_object_parts(heap, &res->obj, hobject_flags);
48762 
48763 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48764  res->ptr_curr_pc = NULL;
48765  res->heap = NULL;
48766  res->valstack = NULL;
48767  res->valstack_end = NULL;
48768  res->valstack_bottom = NULL;
48769  res->valstack_top = NULL;
48770  res->callstack = NULL;
48771  res->catchstack = NULL;
48772  res->resumer = NULL;
48773  res->compile_ctx = NULL,
48774 #if defined(DUK_USE_HEAPPTR16)
48775  res->strs16 = NULL;
48776 #else
48777  res->strs = NULL;
48778 #endif
48779  {
48780  int i;
48781  for (i = 0; i < DUK_NUM_BUILTINS; i++) {
48782  res->builtins[i] = NULL;
48783  }
48784  }
48785 #endif
48786  /* when nothing is running, API calls are in non-strict mode */
48787  DUK_ASSERT(res->strict == 0);
48788 
48789  res->heap = heap;
48790  res->valstack_max = DUK_VALSTACK_DEFAULT_MAX;
48791  res->callstack_max = DUK_CALLSTACK_DEFAULT_MAX;
48792  res->catchstack_max = DUK_CATCHSTACK_DEFAULT_MAX;
48793 
48794  return res;
48795 }
48796 
48797 #if 0 /* unused now */
48798 DUK_INTERNAL duk_hobject *duk_hobject_alloc_checked(duk_hthread *thr, duk_uint_t hobject_flags) {
48799  duk_hobject *res = duk_hobject_alloc(thr->heap, hobject_flags);
48800  if (!res) {
48801  DUK_ERROR_ALLOC_FAILED(thr);
48802  }
48803  return res;
48804 }
48805 #endif
48806 
48807 /*
48808  * Allocate a new array.
48809  */
48810 
48811 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
48812  duk_harray *res;
48813 
48814  res = (duk_harray *) DUK_ALLOC(heap, sizeof(duk_harray));
48815  if (!res) {
48816  return NULL;
48817  }
48818  DUK_MEMZERO(res, sizeof(duk_harray));
48819 
48820  duk__init_object_parts(heap, &res->obj, hobject_flags);
48821 
48822  DUK_ASSERT(res->length == 0);
48823 
48824  return res;
48825 }
48826 /*
48827  * Object enumeration support.
48828  *
48829  * Creates an internal enumeration state object to be used e.g. with for-in
48830  * enumeration. The state object contains a snapshot of target object keys
48831  * and internal control state for enumeration. Enumerator flags allow caller
48832  * to e.g. request internal/non-enumerable properties, and to enumerate only
48833  * "own" properties.
48834  *
48835  * Also creates the result value for e.g. Object.keys() based on the same
48836  * internal structure.
48837  *
48838  * This snapshot-based enumeration approach is used to simplify enumeration:
48839  * non-snapshot-based approaches are difficult to reconcile with mutating
48840  * the enumeration target, running multiple long-lived enumerators at the
48841  * same time, garbage collection details, etc. The downside is that the
48842  * enumerator object is memory inefficient especially for iterating arrays.
48843  */
48844 
48845 /* #include duk_internal.h -> already included */
48846 
48847 /* XXX: identify enumeration target with an object index (not top of stack) */
48848 
48849 /* First enumerated key index in enumerator object, must match exactly the
48850  * number of control properties inserted to the enumerator.
48851  */
48852 #define DUK__ENUM_START_INDEX 2
48853 
48854 #if 0
48855 /* Current implementation suffices for ES2015 for now because there's no symbol
48856  * sorting, so commented out for now.
48857  */
48858 
48859 /*
48860  * Helper to sort enumeration keys using a callback for pairwise duk_hstring
48861  * comparisons. The keys are in the enumeration object entry part, starting
48862  * from DUK__ENUM_START_INDEX, and the entry part is dense. Entry part values
48863  * are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true "2" -> true,
48864  * so it suffices to just switch keys without switching values.
48865  *
48866  * Insertion sort is used because (1) it's simple and compact, (2) works
48867  * in-place, (3) minimizes operations if data is already nearly sorted,
48868  * (4) doesn't reorder elements considered equal.
48869  * http://en.wikipedia.org/wiki/Insertion_sort
48870  */
48871 
48872 typedef duk_bool_t (*duk__sort_compare_fn)(duk_hstring *a, duk_hstring *b, duk_uarridx_t val_b);
48873 
48874 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk_uarridx_t val_b) {
48875  duk_uarridx_t val_a;
48876 
48877  DUK_ASSERT(a != NULL);
48878  DUK_ASSERT(b != NULL);
48879  DUK_UNREF(b); /* Not actually needed now, val_b suffices. */
48880 
48881  /* ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
48882  * (1) array indices in ascending order, (2) non-array-index keys in
48883  * insertion order, symbols in insertion order:
48884  * http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
48885  *
48886  * This rule is applied to "own properties" at each inheritance level;
48887  * non-duplicate parent keys always follow child keys. For example,
48888  * an inherited array index will enumerate -after- a symbol in the
48889  * child.
48890  */
48891 
48892  val_a = DUK_HSTRING_GET_ARRIDX_FAST(a);
48893 
48894  if (val_b < val_a) {
48895  /* Covers:
48896  * - Both keys are array indices and a > b: don't insert here.
48897  * - 'b' is array index, 'a' is not: don't insert here.
48898  */
48899  return 0;
48900  } else {
48901  /* Covers:
48902  * val_a < val_b where:
48903  * - Both keys are array indices and a < b: insert here.
48904  * - 'a' is array index, 'b' is not: insert here.
48905  * val_a == val_b where:
48906  * - Both keys are array indices and a == b: insert here
48907  * (shouldn't actually happen, can't have non-duplicate
48908  * identical array index keys).
48909  * - Neither key is an array index: insert here, keeps key
48910  * order regardless of the keys themselves.
48911  */
48912  return 1;
48913  }
48914 }
48915 
48916 DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end) {
48917  duk_hstring **keys;
48918  duk_int_fast32_t idx;
48919 
48920  DUK_ASSERT(h_obj != NULL);
48921  DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
48922  DUK_ASSERT(idx_end >= idx_start);
48923  DUK_UNREF(thr);
48924 
48925  if (idx_end <= idx_start + 1) {
48926  return; /* Zero or one element(s). */
48927  }
48928 
48929  keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
48930 
48931  for (idx = idx_start + 1; idx < idx_end; idx++) {
48932  duk_hstring *h_curr;
48933  duk_int_fast32_t idx_insert;
48934  duk_uarridx_t val_curr;
48935 
48936  h_curr = keys[idx];
48937  DUK_ASSERT(h_curr != NULL);
48938 
48939  /* Scan backwards for insertion place. This works very well
48940  * when the elements are nearly in order which is the common
48941  * (and optimized for) case.
48942  */
48943 
48944  val_curr = DUK_HSTRING_GET_ARRIDX_FAST(h_curr); /* Remains same during scanning. */
48945  for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
48946  duk_hstring *h_insert;
48947  h_insert = keys[idx_insert];
48948  DUK_ASSERT(h_insert != NULL);
48949 
48950  /* XXX: fixed callback rather than a callback argument; only
48951  * one argument used and using a callback argument doesn't
48952  * cause e.g. gcc to inline the callback.
48953  */
48954  if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
48955  break;
48956  }
48957  }
48958  /* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
48959  * brings us back to idx_start.
48960  */
48961  idx_insert++;
48962  DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
48963 
48964  /* .-- p_insert .-- p_curr
48965  * v v
48966  * | ... | insert | ... | curr
48967  */
48968 
48969  /* This could also done when the keys are in order, i.e.
48970  * idx_insert == idx. The result would be an unnecessary
48971  * memmove() but we use an explicit check because the keys
48972  * are very often in order already.
48973  */
48974  if (idx != idx_insert) {
48975  DUK_MEMMOVE((void *) (keys + idx_insert + 1),
48976  (const void *) (keys + idx_insert),
48977  (size_t) ((idx - idx_insert) * sizeof(duk_hstring *)));
48978  keys[idx_insert] = h_curr;
48979  }
48980  }
48981 }
48982 #endif /* disabled */
48983 
48984 /*
48985  * Helper to sort keys into ES2015 [[OwnPropertyKeys]] enumeration order:
48986  * array keys in ascending order first, followed by keys in insertion
48987  * order, followed by symbols in insertion order (not handled here).
48988  * Insertion sort based.
48989  *
48990  * This algorithm nominally sorts array indices, but because the "no array
48991  * index" marker is higher than any array index, non-array-index keys are
48992  * sorted after array indices. Non-array-index keys are also considered
48993  * equal for sorting which means that their order is kept as is, so the end
48994  * result matches ES2015 [[OwnPropertyKeys]].
48995  *
48996  * Insertion sort is used because (1) it's simple and compact, (2) works
48997  * in-place, (3) minimizes operations if data is already nearly sorted,
48998  * (4) doesn't reorder elements considered equal.
48999  * http://en.wikipedia.org/wiki/Insertion_sort
49000  */
49001 
49002 DUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end) {
49003  duk_hstring **keys;
49004  duk_hstring **p_curr, **p_insert, **p_end;
49005  duk_hstring *h_curr;
49006  duk_uarridx_t val_highest, val_curr, val_insert;
49007 
49008  DUK_ASSERT(h_obj != NULL);
49009  DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
49010  DUK_ASSERT(idx_end >= idx_start);
49011  DUK_UNREF(thr);
49012 
49013  if (idx_end <= idx_start + 1) {
49014  return; /* Zero or one element(s). */
49015  }
49016 
49017  keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
49018  p_curr = keys + idx_start;
49019  val_highest = DUK_HSTRING_GET_ARRIDX_SLOW(*p_curr);
49020  for (p_curr++, p_end = keys + idx_end; p_curr < p_end; p_curr++) {
49021  DUK_ASSERT(*p_curr != NULL);
49022  val_curr = DUK_HSTRING_GET_ARRIDX_SLOW(*p_curr);
49023 
49024  if (val_curr >= val_highest) {
49025  val_highest = val_curr;
49026  continue;
49027  }
49028 
49029  /* Needs to be inserted; scan backwards, since we optimize
49030  * for the case where elements are nearly in order.
49031  */
49032 
49033  p_insert = p_curr;
49034  for (;;) {
49035  p_insert--; /* Start from p_curr - 1. */
49036  val_insert = DUK_HSTRING_GET_ARRIDX_SLOW(*p_insert);
49037  if (val_insert < val_curr) {
49038  p_insert++;
49039  break;
49040  }
49041  if (p_insert == keys + idx_start) {
49042  break;
49043  }
49044  }
49045 
49046  /* .-- p_insert .-- p_curr
49047  * v v
49048  * | ... | insert | ... | curr
49049  */
49050 
49051  h_curr = *p_curr;
49052  DUK_MEMMOVE((void *) (p_insert + 1),
49053  (const void *) p_insert,
49054  (size_t) ((p_curr - p_insert) * sizeof(duk_hstring *)));
49055  *p_insert = h_curr;
49056  /* keep val_highest */
49057  }
49058 }
49059 
49060 /*
49061  * Create an internal enumerator object E, which has its keys ordered
49062  * to match desired enumeration ordering. Also initialize internal control
49063  * properties for enumeration.
49064  *
49065  * Note: if an array was used to hold enumeration keys instead, an array
49066  * scan would be needed to eliminate duplicates found in the prototype chain.
49067  */
49068 
49069 DUK_LOCAL void duk__add_enum_key(duk_context *ctx, duk_hstring *k) {
49070  duk_push_hstring(ctx, k);
49071  duk_push_true(ctx);
49072  duk_put_prop(ctx, -3);
49073 }
49074 
49075 DUK_LOCAL void duk__add_enum_key_stridx(duk_context *ctx, duk_small_uint_t stridx) {
49076  duk__add_enum_key(ctx, DUK_HTHREAD_GET_STRING((duk_hthread *) ctx, stridx));
49077 }
49078 
49079 DUK_INTERNAL void duk_hobject_enumerator_create(duk_context *ctx, duk_small_uint_t enum_flags) {
49080  duk_hthread *thr = (duk_hthread *) ctx;
49081  duk_hobject *enum_target;
49082  duk_hobject *curr;
49083  duk_hobject *res;
49084 #if defined(DUK_USE_ES6_PROXY)
49085  duk_hobject *h_proxy_target;
49086  duk_hobject *h_proxy_handler;
49087  duk_hobject *h_trap_result;
49088 #endif
49089  duk_uint_fast32_t i, len; /* used for array, stack, and entry indices */
49090  duk_uint_fast32_t sort_start_index;
49091 
49092  DUK_ASSERT(ctx != NULL);
49093 
49094  enum_target = duk_require_hobject(ctx, -1);
49095  DUK_ASSERT(enum_target != NULL);
49096 
49097  duk_push_bare_object(ctx);
49098  res = duk_known_hobject(ctx, -1);
49099 
49100  /* [enum_target res] */
49101 
49102  /* Target must be stored so that we can recheck whether or not
49103  * keys still exist when we enumerate. This is not done if the
49104  * enumeration result comes from a proxy trap as there is no
49105  * real object to check against.
49106  */
49107  duk_push_hobject(ctx, enum_target);
49108  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_TARGET);
49109 
49110  /* Initialize index so that we skip internal control keys. */
49111  duk_push_int(ctx, DUK__ENUM_START_INDEX);
49112  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_NEXT);
49113 
49114  /*
49115  * Proxy object handling
49116  */
49117 
49118 #if defined(DUK_USE_ES6_PROXY)
49119  if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
49120  goto skip_proxy;
49121  }
49122  if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
49123  enum_target,
49124  &h_proxy_target,
49125  &h_proxy_handler))) {
49126  goto skip_proxy;
49127  }
49128 
49129  /* XXX: share code with Object.keys() Proxy handling */
49130 
49131  /* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
49132  * has been obsoleted and "ownKeys" is used instead.
49133  */
49134  DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
49135  duk_push_hobject(ctx, h_proxy_handler);
49136  if (!duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
49137  /* No need to replace the 'enum_target' value in stack, only the
49138  * enum_target reference. This also ensures that the original
49139  * enum target is reachable, which keeps the proxy and the proxy
49140  * target reachable. We do need to replace the internal _Target.
49141  */
49142  DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
49143  DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
49144  enum_target = h_proxy_target;
49145 
49146  duk_push_hobject(ctx, enum_target); /* -> [ ... enum_target res handler undefined target ] */
49147  duk_put_prop_stridx_short(ctx, -4, DUK_STRIDX_INT_TARGET);
49148 
49149  duk_pop_2(ctx); /* -> [ ... enum_target res ] */
49150  goto skip_proxy;
49151  }
49152 
49153  /* [ ... enum_target res handler trap ] */
49154  duk_insert(ctx, -2);
49155  duk_push_hobject(ctx, h_proxy_target); /* -> [ ... enum_target res trap handler target ] */
49156  duk_call_method(ctx, 1 /*nargs*/); /* -> [ ... enum_target res trap_result ] */
49157  h_trap_result = duk_require_hobject(ctx, -1);
49158  DUK_UNREF(h_trap_result);
49159 
49160  duk_proxy_ownkeys_postprocess(ctx, h_proxy_target, enum_flags);
49161  /* -> [ ... enum_target res trap_result keys_array ] */
49162 
49163  /* Copy cleaned up trap result keys into the enumerator object. */
49164  /* XXX: result is a dense array; could make use of that. */
49165  DUK_ASSERT(duk_is_array(ctx, -1));
49166  len = (duk_uint_fast32_t) duk_get_length(ctx, -1);
49167  for (i = 0; i < len; i++) {
49168  (void) duk_get_prop_index(ctx, -1, i);
49169  DUK_ASSERT(duk_is_string(ctx, -1)); /* postprocess cleaned up */
49170  /* [ ... enum_target res trap_result keys_array val ] */
49171  duk_push_true(ctx);
49172  /* [ ... enum_target res trap_result keys_array val true ] */
49173  duk_put_prop(ctx, -5);
49174  }
49175  /* [ ... enum_target res trap_result keys_array ] */
49176  duk_pop_2(ctx);
49177  duk_remove_m2(ctx);
49178 
49179  /* [ ... res ] */
49180 
49181  /* The internal _Target property is kept pointing to the original
49182  * enumeration target (the proxy object), so that the enumerator
49183  * 'next' operation can read property values if so requested. The
49184  * fact that the _Target is a proxy disables key existence check
49185  * during enumeration.
49186  */
49187  DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
49188  goto compact_and_return;
49189 
49190  skip_proxy:
49191 #endif /* DUK_USE_ES6_PROXY */
49192 
49193  curr = enum_target;
49194  sort_start_index = DUK__ENUM_START_INDEX;
49195  DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
49196  while (curr) {
49197  duk_uint_fast32_t sort_end_index;
49198 #if !defined(DUK_USE_PREFER_SIZE)
49199  duk_bool_t need_sort = 0;
49200 #endif
49201 
49202  /* Enumeration proceeds by inheritance level. Virtual
49203  * properties need to be handled specially, followed by
49204  * array part, and finally entry part.
49205  *
49206  * If there are array index keys in the entry part or any
49207  * other risk of the ES2015 [[OwnPropertyKeys]] order being
49208  * violated, need_sort is set and an explicit ES2015 sort is
49209  * done for the inheritance level.
49210  */
49211 
49212  /* XXX: inheriting from proxy */
49213 
49214  /*
49215  * Virtual properties.
49216  *
49217  * String and buffer indices are virtual and always enumerable,
49218  * 'length' is virtual and non-enumerable. Array and arguments
49219  * object props have special behavior but are concrete.
49220  *
49221  * String and buffer objects don't have an array part so as long
49222  * as virtual array index keys are enumerated first, we don't
49223  * need to set need_sort.
49224  */
49225 
49226 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49227  if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr)) {
49228 #else
49229  if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
49230 #endif
49231  duk_bool_t have_length = 1;
49232 
49233  /* String and buffer enumeration behavior is identical now,
49234  * so use shared handler.
49235  */
49236  if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
49237  duk_hstring *h_val;
49238  h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
49239  DUK_ASSERT(h_val != NULL); /* string objects must not created without internal value */
49240  len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
49241  }
49242 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
49243  else {
49244  duk_hbufobj *h_bufobj;
49245  DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
49246  h_bufobj = (duk_hbufobj *) curr;
49247 
49248  if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
49249  /* Zero length seems like a good behavior for neutered buffers.
49250  * ArrayBuffer (non-view) and DataView don't have index properties
49251  * or .length property.
49252  */
49253  len = 0;
49254  have_length = 0;
49255  } else {
49256  /* There's intentionally no check for
49257  * current underlying buffer length.
49258  */
49259  len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
49260  }
49261  }
49262 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
49263 
49264  for (i = 0; i < len; i++) {
49265  duk_hstring *k;
49266 
49267  /* This is a bit fragile: the string is not
49268  * reachable until it is pushed by the helper.
49269  */
49270  k = duk_heap_string_intern_u32_checked(thr, i);
49271  DUK_ASSERT(k);
49272 
49273  duk__add_enum_key(ctx, k);
49274 
49275  /* [enum_target res] */
49276  }
49277 
49278  /* 'length' and other virtual properties are not
49279  * enumerable, but are included if non-enumerable
49280  * properties are requested.
49281  */
49282 
49283  if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
49284  duk__add_enum_key_stridx(ctx, DUK_STRIDX_LENGTH);
49285  }
49286  } else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(curr)) {
49287  if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
49288  duk__add_enum_key_stridx(ctx, DUK_STRIDX_LENGTH);
49289  }
49290  }
49291 
49292  /*
49293  * Array part
49294  */
49295 
49296  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
49297  duk_hstring *k;
49298  duk_tval *tv;
49299 
49300  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
49301  if (DUK_TVAL_IS_UNUSED(tv)) {
49302  continue;
49303  }
49304  k = duk_heap_string_intern_u32_checked(thr, i); /* Fragile reachability. */
49305  DUK_ASSERT(k);
49306 
49307  duk__add_enum_key(ctx, k);
49308 
49309  /* [enum_target res] */
49310  }
49311 
49312  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
49313  /* Array .length comes after numeric indices. */
49314  if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
49315  duk__add_enum_key_stridx(ctx, DUK_STRIDX_LENGTH);
49316  }
49317  }
49318 
49319  /*
49320  * Entries part
49321  */
49322 
49323  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
49324  duk_hstring *k;
49325 
49326  k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
49327  if (!k) {
49328  continue;
49329  }
49330  if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
49331  !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
49332  continue;
49333  }
49334  if (DUK_HSTRING_HAS_SYMBOL(k)) {
49335  if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
49336  DUK_HSTRING_HAS_HIDDEN(k)) {
49337  continue;
49338  }
49339  if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
49340  continue;
49341  }
49342  } else {
49343  DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k)); /* would also have symbol flag */
49344  if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
49345  continue;
49346  }
49347  }
49348  if (DUK_HSTRING_HAS_ARRIDX(k)) {
49349  /* This in currently only possible if the
49350  * object has no array part: the array part
49351  * is exhaustive when it is present.
49352  */
49353 #if !defined(DUK_USE_PREFER_SIZE)
49354  need_sort = 1;
49355 #endif
49356  } else {
49357  if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
49358  continue;
49359  }
49360  }
49361 
49362  DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
49363  !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
49364 
49365  duk__add_enum_key(ctx, k);
49366 
49367  /* [enum_target res] */
49368  }
49369 
49370  /* Sort enumerated keys according to ES2015 requirements for
49371  * the "inheritance level" just processed. This is far from
49372  * optimal, ES2015 semantics could be achieved more efficiently
49373  * by handling array index string keys (and symbol keys)
49374  * specially above in effect doing the sort inline.
49375  *
49376  * Skip the sort if array index sorting is requested because
49377  * we must consider all keys, also inherited, so an explicit
49378  * sort is done for the whole result after we're done with the
49379  * prototype chain.
49380  *
49381  * Also skip the sort if need_sort == 0, i.e. we know for
49382  * certain that the enumerated order is already correct.
49383  */
49384  sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
49385 
49386  if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
49387 #if defined(DUK_USE_PREFER_SIZE)
49388  duk__sort_enum_keys_es6(thr, res, sort_start_index, sort_end_index);
49389 #else
49390  if (need_sort) {
49391  DUK_DDD(DUK_DDDPRINT("need to sort"));
49392  duk__sort_enum_keys_es6(thr, res, sort_start_index, sort_end_index);
49393  } else {
49394  DUK_DDD(DUK_DDDPRINT("no need to sort"));
49395  }
49396 #endif
49397  }
49398 
49399  sort_start_index = sort_end_index;
49400 
49401  if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
49402  break;
49403  }
49404 
49405  curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
49406  }
49407 
49408  /* [enum_target res] */
49409 
49410  duk_remove_m2(ctx);
49411 
49412  /* [res] */
49413 
49414  if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
49415  /* Some E5/E5.1 algorithms require that array indices are iterated
49416  * in a strictly ascending order. This is the case for e.g.
49417  * Array.prototype.forEach() and JSON.stringify() PropertyList
49418  * handling. The caller can request an explicit sort in these
49419  * cases.
49420  */
49421 
49422  /* Sort to ES2015 order which works for pure array incides but
49423  * also for mixed keys.
49424  */
49425  duk__sort_enum_keys_es6(thr, res, DUK__ENUM_START_INDEX, DUK_HOBJECT_GET_ENEXT(res));
49426  }
49427 
49428 #if defined(DUK_USE_ES6_PROXY)
49429  compact_and_return:
49430 #endif
49431  /* compact; no need to seal because object is internal */
49432  duk_hobject_compact_props(thr, res);
49433 
49434  DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
49435 }
49436 
49437 /*
49438  * Returns non-zero if a key and/or value was enumerated, and:
49439  *
49440  * [enum] -> [key] (get_value == 0)
49441  * [enum] -> [key value] (get_value == 1)
49442  *
49443  * Returns zero without pushing anything on the stack otherwise.
49444  */
49445 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_context *ctx, duk_bool_t get_value) {
49446  duk_hthread *thr = (duk_hthread *) ctx;
49447  duk_hobject *e;
49448  duk_hobject *enum_target;
49449  duk_hstring *res = NULL;
49450  duk_uint_fast32_t idx;
49451  duk_bool_t check_existence;
49452 
49453  DUK_ASSERT(ctx != NULL);
49454 
49455  /* [... enum] */
49456 
49457  e = duk_require_hobject(ctx, -1);
49458 
49459  /* XXX use get tval ptr, more efficient */
49460  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_NEXT);
49461  idx = (duk_uint_fast32_t) duk_require_uint(ctx, -1);
49462  duk_pop(ctx);
49463  DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
49464 
49465  /* Enumeration keys are checked against the enumeration target (to see
49466  * that they still exist). In the proxy enumeration case _Target will
49467  * be the proxy, and checking key existence against the proxy is not
49468  * required (or sensible, as the keys may be fully virtual).
49469  */
49470  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_TARGET);
49471  enum_target = duk_require_hobject(ctx, -1);
49472  DUK_ASSERT(enum_target != NULL);
49473 #if defined(DUK_USE_ES6_PROXY)
49474  check_existence = (!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(enum_target));
49475 #else
49476  check_existence = 1;
49477 #endif
49478  duk_pop(ctx); /* still reachable */
49479 
49480  DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
49481  (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(ctx, -1)));
49482 
49483  /* no array part */
49484  for (;;) {
49485  duk_hstring *k;
49486 
49487  if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
49488  DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
49489  break;
49490  }
49491 
49492  /* we know these because enum objects are internally created */
49493  k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
49494  DUK_ASSERT(k != NULL);
49495  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
49496  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
49497 
49498  idx++;
49499 
49500  /* recheck that the property still exists */
49501  if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
49502  DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
49503  continue;
49504  }
49505 
49506  DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
49507  res = k;
49508  break;
49509  }
49510 
49511  DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
49512 
49513  duk_push_u32(ctx, (duk_uint32_t) idx);
49514  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_NEXT);
49515 
49516  /* [... enum] */
49517 
49518  if (res) {
49519  duk_push_hstring(ctx, res);
49520  if (get_value) {
49521  duk_push_hobject(ctx, enum_target);
49522  duk_dup_m2(ctx); /* -> [... enum key enum_target key] */
49523  duk_get_prop(ctx, -2); /* -> [... enum key enum_target val] */
49524  duk_remove_m2(ctx); /* -> [... enum key val] */
49525  duk_remove(ctx, -3); /* -> [... key val] */
49526  } else {
49527  duk_remove_m2(ctx); /* -> [... key] */
49528  }
49529  return 1;
49530  } else {
49531  duk_pop(ctx); /* -> [...] */
49532  return 0;
49533  }
49534 }
49535 
49536 /*
49537  * Get enumerated keys in an Ecmascript array. Matches Object.keys() behavior
49538  * described in E5 Section 15.2.3.14.
49539  */
49540 
49541 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_context *ctx, duk_small_uint_t enum_flags) {
49542  duk_hthread *thr = (duk_hthread *) ctx;
49543  duk_hobject *e;
49544  duk_harray *a;
49545  duk_hstring **keys;
49546  duk_tval *tv;
49547  duk_uint_fast32_t count;
49548 
49549  DUK_ASSERT(ctx != NULL);
49550  DUK_ASSERT(duk_get_hobject(ctx, -1) != NULL);
49551  DUK_UNREF(thr);
49552 
49553  /* Create a temporary enumerator to get the (non-duplicated) key list;
49554  * the enumerator state is initialized without being needed, but that
49555  * has little impact.
49556  */
49557 
49558  duk_hobject_enumerator_create(ctx, enum_flags);
49559  e = duk_known_hobject(ctx, -1);
49560 
49561  /* [enum_target enum res] */
49562 
49563  /* Create dense result array to exact size. */
49564  DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
49565  count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
49566 
49567  a = duk_push_harray_with_size(ctx, count);
49568  DUK_ASSERT(a != NULL);
49569  DUK_ASSERT(DUK_HOBJECT_GET_ASIZE((duk_hobject *) a) == count);
49570  DUK_ASSERT(a->length == count);
49571  tv = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
49572 
49573  /* Fill result array, no side effects. */
49574 
49575  keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
49576  keys += DUK__ENUM_START_INDEX;
49577 
49578  while (count-- > 0) {
49579  duk_hstring *k;
49580 
49581  k = *keys++;
49582  DUK_ASSERT(k != NULL); /* enumerator must have no keys deleted */
49583 
49584  DUK_TVAL_SET_STRING(tv, k);
49585  tv++;
49586  DUK_HSTRING_INCREF(thr, k);
49587  }
49588 
49589  /* [enum_target enum res] */
49590  duk_remove_m2(ctx);
49591 
49592  /* [enum_target res] */
49593 
49594  return 1; /* return 1 to allow callers to tail call */
49595 }
49596 
49597 /* automatic undefs */
49598 #undef DUK__ENUM_START_INDEX
49599 /*
49600  * Run an duk_hobject finalizer. Used for both reference counting
49601  * and mark-and-sweep algorithms. Must never throw an error.
49602  *
49603  * There is no return value. Any return value or error thrown by
49604  * the finalizer is ignored (although errors are debug logged).
49605  *
49606  * Notes:
49607  *
49608  * - The thread used for calling the finalizer is the same as the
49609  * 'thr' argument. This may need to change later.
49610  *
49611  * - The finalizer thread 'top' assertions are there because it is
49612  * critical that strict stack policy is observed (i.e. no cruft
49613  * left on the finalizer stack).
49614  */
49615 
49616 /* #include duk_internal.h -> already included */
49617 
49618 #if defined(DUK_USE_FINALIZER_SUPPORT)
49619 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_context *ctx, void *udata) {
49620  duk_hthread *thr;
49621 
49622  DUK_ASSERT(ctx != NULL);
49623  thr = (duk_hthread *) ctx;
49624  DUK_UNREF(udata);
49625 
49626  DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
49627 
49628  /* [... obj] */
49629 
49630  /* XXX: Finalizer lookup should traverse the prototype chain (to allow
49631  * inherited finalizers) but should not invoke accessors or proxy object
49632  * behavior. At the moment this lookup will invoke proxy behavior, so
49633  * caller must ensure that this function is not called if the target is
49634  * a Proxy.
49635  */
49636 
49637  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_FINALIZER); /* -> [... obj finalizer] */
49638  if (!duk_is_callable(ctx, -1)) {
49639  DUK_DDD(DUK_DDDPRINT("-> no finalizer or finalizer not callable"));
49640  return 0;
49641  }
49642  duk_dup_m2(ctx);
49643  duk_push_boolean(ctx, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
49644  DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling finalizer"));
49645  duk_call(ctx, 2); /* [ ... obj finalizer obj heapDestruct ] -> [ ... obj retval ] */
49646  DUK_DDD(DUK_DDDPRINT("finalizer finished successfully"));
49647  return 0;
49648 
49649  /* Note: we rely on duk_safe_call() to fix up the stack for the caller,
49650  * so we don't need to pop stuff here. There is no return value;
49651  * caller determines rescued status based on object refcount.
49652  */
49653 }
49654 
49655 DUK_INTERNAL void duk_hobject_run_finalizer(duk_hthread *thr, duk_hobject *obj) {
49656  duk_context *ctx = (duk_context *) thr;
49657  duk_ret_t rc;
49658 #if defined(DUK_USE_ASSERTIONS)
49659  duk_idx_t entry_top;
49660 #endif
49661 
49662  DUK_DDD(DUK_DDDPRINT("running object finalizer for object: %p", (void *) obj));
49663 
49664  DUK_ASSERT(thr != NULL);
49665  DUK_ASSERT(ctx != NULL);
49666  DUK_ASSERT(obj != NULL);
49667  DUK_ASSERT_VALSTACK_SPACE(thr, 1);
49668 
49669 #if defined(DUK_USE_ASSERTIONS)
49670  entry_top = duk_get_top(ctx);
49671 #endif
49672  /*
49673  * Get and call the finalizer. All of this must be wrapped
49674  * in a protected call, because even getting the finalizer
49675  * may trigger an error (getter may throw one, for instance).
49676  */
49677 
49678  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
49679  if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
49680  DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
49681  return;
49682  }
49683  DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj); /* ensure never re-entered until rescue cycle complete */
49684  if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj)) {
49685  /* This shouldn't happen; call sites should avoid looking up
49686  * _Finalizer "through" a Proxy, but ignore if we come here
49687  * with a Proxy to avoid finalizer re-entry.
49688  */
49689  DUK_D(DUK_DPRINT("object is a proxy, skip finalizer call"));
49690  return;
49691  }
49692 
49693  /* XXX: use a NULL error handler for the finalizer call? */
49694 
49695  DUK_DDD(DUK_DDDPRINT("-> finalizer found, calling wrapped finalize helper"));
49696  duk_push_hobject(ctx, obj); /* this also increases refcount by one */
49697  rc = duk_safe_call(ctx, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/); /* -> [... obj retval/error] */
49698  DUK_ASSERT_TOP(ctx, entry_top + 2); /* duk_safe_call discipline */
49699 
49700  if (rc != DUK_EXEC_SUCCESS) {
49701  /* Note: we ask for one return value from duk_safe_call to get this
49702  * error debugging here.
49703  */
49704  DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
49705  (void *) obj, (duk_tval *) duk_get_tval(ctx, -1)));
49706  }
49707  duk_pop_2(ctx); /* -> [...] */
49708 
49709  DUK_ASSERT_TOP(ctx, entry_top);
49710 }
49711 #endif /* DUK_USE_FINALIZER_SUPPORT */
49712 /*
49713  * Misc support functions
49714  */
49715 
49716 /* #include duk_internal.h -> already included */
49717 
49718 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
49719  duk_uint_t sanity;
49720 
49721  DUK_ASSERT(thr != NULL);
49722 
49723  /* False if the object is NULL or the prototype 'p' is NULL.
49724  * In particular, false if both are NULL (don't compare equal).
49725  */
49726  if (h == NULL || p == NULL) {
49727  return 0;
49728  }
49729 
49730  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
49731  do {
49732  if (h == p) {
49733  return 1;
49734  }
49735 
49736  if (sanity-- == 0) {
49737  if (ignore_loop) {
49738  break;
49739  } else {
49740  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
49741  }
49742  }
49743  h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
49744  } while (h);
49745 
49746  return 0;
49747 }
49748 
49749 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
49750 #if defined(DUK_USE_REFERENCE_COUNTING)
49751  duk_hobject *tmp;
49752 
49753  DUK_ASSERT(h);
49754  tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
49755  DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
49756  DUK_HOBJECT_INCREF_ALLOWNULL(thr, p); /* avoid problems if p == h->prototype */
49757  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
49758 #else
49759  DUK_ASSERT(h);
49760  DUK_UNREF(thr);
49761  DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
49762 #endif
49763 }
49764 /*
49765  * Helpers for creating and querying pc2line debug data, which
49766  * converts a bytecode program counter to a source line number.
49767  *
49768  * The run-time pc2line data is bit-packed, and documented in:
49769  *
49770  * doc/function-objects.rst
49771  */
49772 
49773 /* #include duk_internal.h -> already included */
49774 
49775 #if defined(DUK_USE_PC2LINE)
49776 
49777 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
49778 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
49779  duk_context *ctx = (duk_context *) thr;
49780  duk_hbuffer_dynamic *h_buf;
49781  duk_bitencoder_ctx be_ctx_alloc;
49782  duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
49783  duk_uint32_t *hdr;
49784  duk_size_t new_size;
49785  duk_uint_fast32_t num_header_entries;
49786  duk_uint_fast32_t curr_offset;
49787  duk_int_fast32_t curr_line, next_line, diff_line;
49788  duk_uint_fast32_t curr_pc;
49789  duk_uint_fast32_t hdr_index;
49790 
49791  DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
49792 
49793  /* XXX: add proper spare handling to dynamic buffer, to minimize
49794  * reallocs; currently there is no spare at all.
49795  */
49796 
49797  num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
49798  curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
49799 
49800  duk_push_dynamic_buffer(ctx, (duk_size_t) curr_offset);
49801  h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(ctx, -1);
49802  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
49803 
49804  hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
49805  DUK_ASSERT(hdr != NULL);
49806  hdr[0] = (duk_uint32_t) length; /* valid pc range is [0, length[ */
49807 
49808  curr_pc = 0U;
49809  while (curr_pc < length) {
49810  new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
49811  duk_hbuffer_resize(thr, h_buf, new_size);
49812 
49813  hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
49814  DUK_ASSERT(hdr != NULL);
49815  DUK_ASSERT(curr_pc < length);
49816  hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
49817  curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
49818  hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
49819  hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
49820 
49821 #if 0
49822  DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
49823  (long) (curr_pc / DUK_PC2LINE_SKIP),
49824  (long) curr_pc,
49825  (long) hdr[hdr_index + 0],
49826  (long) hdr[hdr_index + 1]));
49827 #endif
49828 
49829  DUK_MEMZERO(be_ctx, sizeof(*be_ctx));
49830  be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
49831  be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
49832 
49833  for (;;) {
49834  curr_pc++;
49835  if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) || /* end of diff run */
49836  (curr_pc >= length) ) { /* end of bytecode */
49837  break;
49838  }
49839  DUK_ASSERT(curr_pc < length);
49840  next_line = (duk_int32_t) instrs[curr_pc].line;
49841  diff_line = next_line - curr_line;
49842 
49843 #if 0
49844  DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
49845  (long) curr_line, (long) next_line, (long) diff_line));
49846 #endif
49847 
49848  if (diff_line == 0) {
49849  /* 0 */
49850  duk_be_encode(be_ctx, 0, 1);
49851  } else if (diff_line >= 1 && diff_line <= 4) {
49852  /* 1 0 <2 bits> */
49853  duk_be_encode(be_ctx, (0x02 << 2) + (diff_line - 1), 4);
49854  } else if (diff_line >= -0x80 && diff_line <= 0x7f) {
49855  /* 1 1 0 <8 bits> */
49856  DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
49857  duk_be_encode(be_ctx, (0x06 << 8) + (diff_line + 0x80), 11);
49858  } else {
49859  /* 1 1 1 <32 bits>
49860  * Encode in two parts to avoid bitencode 24-bit limitation
49861  */
49862  duk_be_encode(be_ctx, (0x07 << 16) + ((next_line >> 16) & 0xffffU), 19);
49863  duk_be_encode(be_ctx, next_line & 0xffffU, 16);
49864  }
49865 
49866  curr_line = next_line;
49867  }
49868 
49869  duk_be_finish(be_ctx);
49870  DUK_ASSERT(!be_ctx->truncated);
49871 
49872  /* be_ctx->offset == length of encoded bitstream */
49873  curr_offset += (duk_uint_fast32_t) be_ctx->offset;
49874  }
49875 
49876  /* compact */
49877  new_size = (duk_size_t) curr_offset;
49878  duk_hbuffer_resize(thr, h_buf, new_size);
49879 
49880  (void) duk_to_fixed_buffer(ctx, -1, NULL);
49881 
49882  DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
49883  (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
49884  (duk_tval *) duk_get_tval(ctx, -1)));
49885 }
49886 
49887 /* PC is unsigned. If caller does PC arithmetic and gets a negative result,
49888  * it will map to a large PC which is out of bounds and causes a zero to be
49889  * returned.
49890  */
49891 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
49892  duk_bitdecoder_ctx bd_ctx_alloc;
49893  duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
49894  duk_uint32_t *hdr;
49895  duk_uint_fast32_t start_offset;
49896  duk_uint_fast32_t pc_limit;
49897  duk_uint_fast32_t hdr_index;
49898  duk_uint_fast32_t pc_base;
49899  duk_uint_fast32_t n;
49900  duk_uint_fast32_t curr_line;
49901 
49902  DUK_ASSERT(buf != NULL);
49903  DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
49904  DUK_UNREF(thr);
49905 
49906  /*
49907  * Use the index in the header to find the right starting point
49908  */
49909 
49910  hdr_index = pc / DUK_PC2LINE_SKIP;
49911  pc_base = hdr_index * DUK_PC2LINE_SKIP;
49912  n = pc - pc_base;
49913 
49914  if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
49915  DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
49916  goto error;
49917  }
49918 
49919  hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
49920  pc_limit = hdr[0];
49921  if (pc >= pc_limit) {
49922  /* Note: pc is unsigned and cannot be negative */
49923  DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
49924  (long) pc, (long) pc_limit));
49925  goto error;
49926  }
49927 
49928  curr_line = hdr[1 + hdr_index * 2];
49929  start_offset = hdr[1 + hdr_index * 2 + 1];
49930  if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
49931  DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
49932  (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
49933  goto error;
49934  }
49935 
49936  /*
49937  * Iterate the bitstream (line diffs) until PC is reached
49938  */
49939 
49940  DUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));
49941  bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
49942  bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
49943 
49944 #if 0
49945  DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
49946  (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
49947 #endif
49948 
49949  while (n > 0) {
49950 #if 0
49951  DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
49952 #endif
49953 
49954  if (duk_bd_decode_flag(bd_ctx)) {
49955  if (duk_bd_decode_flag(bd_ctx)) {
49956  if (duk_bd_decode_flag(bd_ctx)) {
49957  /* 1 1 1 <32 bits> */
49958  duk_uint_fast32_t t;
49959  t = duk_bd_decode(bd_ctx, 16); /* workaround: max nbits = 24 now */
49960  t = (t << 16) + duk_bd_decode(bd_ctx, 16);
49961  curr_line = t;
49962  } else {
49963  /* 1 1 0 <8 bits> */
49964  duk_uint_fast32_t t;
49965  t = duk_bd_decode(bd_ctx, 8);
49966  curr_line = curr_line + t - 0x80;
49967  }
49968  } else {
49969  /* 1 0 <2 bits> */
49970  duk_uint_fast32_t t;
49971  t = duk_bd_decode(bd_ctx, 2);
49972  curr_line = curr_line + t + 1;
49973  }
49974  } else {
49975  /* 0: no change */
49976  }
49977 
49978  n--;
49979  }
49980 
49981  DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
49982  return curr_line;
49983 
49984  error:
49985  DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
49986  return 0;
49987 }
49988 
49989 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_context *ctx, duk_idx_t idx_func, duk_uint_fast32_t pc) {
49990  duk_hbuffer_fixed *pc2line;
49991  duk_uint_fast32_t line;
49992 
49993  /* XXX: now that pc2line is used by the debugger quite heavily in
49994  * checked execution, this should be optimized to avoid value stack
49995  * and perhaps also implement some form of pc2line caching (see
49996  * future work in debugger.rst).
49997  */
49998 
49999  duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_PC2LINE);
50000  pc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(ctx, -1);
50001  if (pc2line != NULL) {
50002  DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
50003  line = duk__hobject_pc2line_query_raw((duk_hthread *) ctx, pc2line, (duk_uint_fast32_t) pc);
50004  } else {
50005  line = 0;
50006  }
50007  duk_pop(ctx);
50008 
50009  return line;
50010 }
50011 
50012 #endif /* DUK_USE_PC2LINE */
50013 /*
50014  * Hobject property set/get functionality.
50015  *
50016  * This is very central functionality for size, performance, and compliance.
50017  * It is also rather intricate; see hobject-algorithms.rst for discussion on
50018  * the algorithms and memory-management.rst for discussion on refcounts and
50019  * side effect issues.
50020  *
50021  * Notes:
50022  *
50023  * - It might be tempting to assert "refcount nonzero" for objects
50024  * being operated on, but that's not always correct: objects with
50025  * a zero refcount may be operated on by the refcount implementation
50026  * (finalization) for instance. Hence, no refcount assertions are made.
50027  *
50028  * - Many operations (memory allocation, identifier operations, etc)
50029  * may cause arbitrary side effects (e.g. through GC and finalization).
50030  * These side effects may invalidate duk_tval pointers which point to
50031  * areas subject to reallocation (like value stack). Heap objects
50032  * themselves have stable pointers. Holding heap object pointers or
50033  * duk_tval copies is not problematic with respect to side effects;
50034  * care must be taken when holding and using argument duk_tval pointers.
50035  *
50036  * - If a finalizer is executed, it may operate on the the same object
50037  * we're currently dealing with. For instance, the finalizer might
50038  * delete a certain property which has already been looked up and
50039  * confirmed to exist. Ideally finalizers would be disabled if GC
50040  * happens during property access. At the moment property table realloc
50041  * disables finalizers, and all DECREFs may cause arbitrary changes so
50042  * handle DECREF carefully.
50043  *
50044  * - The order of operations for a DECREF matters. When DECREF is executed,
50045  * the entire object graph must be consistent; note that a refzero may
50046  * lead to a mark-and-sweep through a refcount finalizer. Use NORZ macros
50047  * and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
50048  */
50049 
50050 /*
50051  * XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
50052  * might be more appropriate.
50053  */
50054 
50055 /*
50056  * XXX: duk_uint_fast32_t should probably be used in many places here.
50057  */
50058 
50059 /* #include duk_internal.h -> already included */
50060 
50061 /*
50062  * Local defines
50063  */
50064 
50065 #define DUK__NO_ARRAY_INDEX DUK_HSTRING_NO_ARRAY_INDEX
50066 
50067 /* hash probe sequence */
50068 #define DUK__HASH_INITIAL(hash,h_size) DUK_HOBJECT_HASH_INITIAL((hash),(h_size))
50069 #define DUK__HASH_PROBE_STEP(hash) DUK_HOBJECT_HASH_PROBE_STEP((hash))
50070 
50071 /* marker values for hash part */
50072 #define DUK__HASH_UNUSED DUK_HOBJECT_HASHIDX_UNUSED
50073 #define DUK__HASH_DELETED DUK_HOBJECT_HASHIDX_DELETED
50074 
50075 /* valstack space that suffices for all local calls, including recursion
50076  * of other than Duktape calls (getters etc)
50077  */
50078 #define DUK__VALSTACK_SPACE 10
50079 
50080 /* valstack space allocated especially for proxy lookup which does a
50081  * recursive property lookup
50082  */
50083 #define DUK__VALSTACK_PROXY_LOOKUP 20
50084 
50085 /*
50086  * Local prototypes
50087  */
50088 
50089 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);
50090 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);
50091 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
50092 
50093 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);
50094 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
50095 
50096 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);
50097 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);
50098 
50099 /*
50100  * Misc helpers
50101  */
50102 
50103 /* Convert a duk_tval number (caller checks) to a 32-bit index. Returns
50104  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
50105  * index.
50106  */
50107 /* XXX: for fastints, could use a variant which assumes a double duk_tval
50108  * (and doesn't need to check for fastint again).
50109  */
50110 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
50111  duk_double_t dbl;
50112  duk_uint32_t idx;
50113 
50114  DUK_ASSERT(tv != NULL);
50115  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
50116 
50117  /* -0 is accepted here as index 0 because ToString(-0) == "0" which is
50118  * in canonical form and thus an array index.
50119  */
50120  dbl = DUK_TVAL_GET_NUMBER(tv);
50121  idx = (duk_uint32_t) dbl;
50122  if ((duk_double_t) idx == dbl) {
50123  /* Is whole and within 32 bit range. If the value happens to be 0xFFFFFFFF,
50124  * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
50125  */
50126  return idx;
50127  }
50128  return DUK__NO_ARRAY_INDEX;
50129 }
50130 
50131 #if defined(DUK_USE_FASTINT)
50132 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
50133 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
50134  duk_int64_t t;
50135 
50136  DUK_ASSERT(tv != NULL);
50137  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
50138 
50139  t = DUK_TVAL_GET_FASTINT(tv);
50140  if ((t & ~0xffffffffULL) != 0) {
50141  /* Catches >0x100000000 and negative values. */
50142  return DUK__NO_ARRAY_INDEX;
50143  }
50144 
50145  /* If the value happens to be 0xFFFFFFFF, it's not a valid array index
50146  * but will then match DUK__NO_ARRAY_INDEX.
50147  */
50148  return (duk_uint32_t) t;
50149 }
50150 #endif /* DUK_USE_FASTINT */
50151 
50152 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
50153  * to a string or symbol using ES2015 ToPropertyKey():
50154  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
50155  *
50156  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
50157  * if not).
50158  */
50159 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_context *ctx, duk_idx_t idx, duk_hstring **out_h) {
50160  duk_uint32_t arr_idx;
50161  duk_hstring *h;
50162  duk_tval *tv_dst;
50163 
50164  DUK_ASSERT(ctx != NULL);
50165  DUK_ASSERT(out_h != NULL);
50166  DUK_ASSERT(duk_is_valid_index(ctx, idx));
50167  DUK_ASSERT(idx < 0);
50168 
50169  /* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
50170  * ToString()) involves a ToPrimitive(), a symbol check, and finally
50171  * a ToString(). Figure out the best way to have a good fast path
50172  * but still be compliant and share code.
50173  */
50174 
50175  tv_dst = DUK_GET_TVAL_NEGIDX((duk_hthread *) ctx, idx); /* intentionally unvalidated */
50176  if (DUK_TVAL_IS_STRING(tv_dst)) {
50177  /* Most important path: strings and plain symbols are used as
50178  * is. For symbols the array index check below is unnecessary
50179  * (they're never valid array indices) but checking that the
50180  * string is a symbol would make the plain string path slower
50181  * unnecessarily.
50182  */
50183  h = DUK_TVAL_GET_STRING(tv_dst);
50184  } else {
50185  h = duk_to_property_key_hstring(ctx, idx);
50186  }
50187  DUK_ASSERT(h != NULL);
50188  *out_h = h;
50189 
50190  arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
50191  return arr_idx;
50192 }
50193 
50194 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_context *ctx, duk_tval *tv_key, duk_hstring **out_h) {
50195  duk_push_tval(ctx, tv_key); /* XXX: could use an unsafe push here */
50196  return duk__to_property_key(ctx, -1, out_h);
50197 }
50198 
50199 /* String is an own (virtual) property of a lightfunc. */
50200 DUK_LOCAL duk_bool_t duk__key_is_lightfunc_ownprop(duk_hthread *thr, duk_hstring *key) {
50201  DUK_UNREF(thr);
50202  return (key == DUK_HTHREAD_STRING_LENGTH(thr) ||
50203  key == DUK_HTHREAD_STRING_NAME(thr));
50204 }
50205 
50206 /* String is an own (virtual) property of a plain buffer. */
50207 DUK_LOCAL duk_bool_t duk__key_is_plain_buf_ownprop(duk_hthread *thr, duk_hbuffer *buf, duk_hstring *key, duk_uint32_t arr_idx) {
50208  DUK_UNREF(thr);
50209 
50210  /* Virtual index properties. Checking explicitly for
50211  * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
50212  * because DUK__NO_ARRAY_INDEXi is always larger than
50213  * maximum allowed buffer size.
50214  */
50215  DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
50216  if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
50217  return 1;
50218  }
50219 
50220  /* Other virtual properties. */
50221  return (key == DUK_HTHREAD_STRING_LENGTH(thr));
50222 }
50223 
50224 /*
50225  * Helpers for managing property storage size
50226  */
50227 
50228 /* Get default hash part size for a certain entry part size. */
50229 #if defined(DUK_USE_HOBJECT_HASH_PART)
50230 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
50231  DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
50232 
50233  if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
50234  duk_uint32_t res;
50235 
50236  /* result: hash_prime(floor(1.2 * e_size)) */
50237  res = duk_util_get_hash_prime(e_size + e_size / DUK_HOBJECT_H_SIZE_DIVISOR);
50238 
50239  /* if fails, e_size will be zero = not an issue, except performance-wise */
50240  DUK_ASSERT(res == 0 || res > e_size);
50241  return res;
50242  } else {
50243  return 0;
50244  }
50245 }
50246 #endif /* USE_PROP_HASH_PART */
50247 
50248 /* Get minimum entry part growth for a certain size. */
50249 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
50250  duk_uint32_t res;
50251 
50252  DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
50253 
50254  res = (e_size + DUK_HOBJECT_E_MIN_GROW_ADD) / DUK_HOBJECT_E_MIN_GROW_DIVISOR;
50255  DUK_ASSERT(res >= 1); /* important for callers */
50256  return res;
50257 }
50258 
50259 /* Get minimum array part growth for a certain size. */
50260 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
50261  duk_uint32_t res;
50262 
50263  DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
50264 
50265  res = (a_size + DUK_HOBJECT_A_MIN_GROW_ADD) / DUK_HOBJECT_A_MIN_GROW_DIVISOR;
50266  DUK_ASSERT(res >= 1); /* important for callers */
50267  return res;
50268 }
50269 
50270 /* Count actually used entry part entries (non-NULL keys). */
50271 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
50272  duk_uint_fast32_t i;
50273  duk_uint_fast32_t n = 0;
50274  duk_hstring **e;
50275 
50276  DUK_ASSERT(obj != NULL);
50277  DUK_UNREF(thr);
50278 
50279  e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
50280  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50281  if (*e++) {
50282  n++;
50283  }
50284  }
50285  return (duk_uint32_t) n;
50286 }
50287 
50288 /* Count actually used array part entries and array minimum size.
50289  * NOTE: 'out_min_size' can be computed much faster by starting from the
50290  * end and breaking out early when finding first used entry, but this is
50291  * not needed now.
50292  */
50293 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
50294  duk_uint_fast32_t i;
50295  duk_uint_fast32_t used = 0;
50296  duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1; /* see below */
50297  duk_tval *a;
50298 
50299  DUK_ASSERT(obj != NULL);
50300  DUK_ASSERT(out_used != NULL);
50301  DUK_ASSERT(out_min_size != NULL);
50302  DUK_UNREF(thr);
50303 
50304  a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
50305  for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
50306  duk_tval *tv = a++;
50307  if (!DUK_TVAL_IS_UNUSED(tv)) {
50308  used++;
50309  highest_idx = i;
50310  }
50311  }
50312 
50313  /* Initial value for highest_idx is -1 coerced to unsigned. This
50314  * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
50315  * for out_min_size as intended.
50316  */
50317 
50318  *out_used = used;
50319  *out_min_size = highest_idx + 1; /* 0 if no used entries */
50320 }
50321 
50322 /* Check array density and indicate whether or not the array part should be abandoned. */
50323 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
50324  /*
50325  * Array abandon check; abandon if:
50326  *
50327  * new_used / new_size < limit
50328  * new_used < limit * new_size || limit is 3 bits fixed point
50329  * new_used < limit' / 8 * new_size || *8
50330  * 8*new_used < limit' * new_size || :8
50331  * new_used < limit' * (new_size / 8)
50332  *
50333  * Here, new_used = a_used, new_size = a_size.
50334  *
50335  * Note: some callers use approximate values for a_used and/or a_size
50336  * (e.g. dropping a '+1' term). This doesn't affect the usefulness
50337  * of the check, but may confuse debugging.
50338  */
50339 
50340  return (a_used < DUK_HOBJECT_A_ABANDON_LIMIT * (a_size >> 3));
50341 }
50342 
50343 /* Fast check for extending array: check whether or not a slow density check is required. */
50344 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
50345  /*
50346  * In a fast check we assume old_size equals old_used (i.e., existing
50347  * array is fully dense).
50348  *
50349  * Slow check if:
50350  *
50351  * (new_size - old_size) / old_size > limit
50352  * new_size - old_size > limit * old_size
50353  * new_size > (1 + limit) * old_size || limit' is 3 bits fixed point
50354  * new_size > (1 + (limit' / 8)) * old_size || * 8
50355  * 8 * new_size > (8 + limit') * old_size || : 8
50356  * new_size > (8 + limit') * (old_size / 8)
50357  * new_size > limit'' * (old_size / 8) || limit'' = 9 -> max 25% increase
50358  * arr_idx + 1 > limit'' * (old_size / 8)
50359  *
50360  * This check doesn't work well for small values, so old_size is rounded
50361  * up for the check (and the '+ 1' of arr_idx can be ignored in practice):
50362  *
50363  * arr_idx > limit'' * ((old_size + 7) / 8)
50364  */
50365 
50366  return (arr_idx > DUK_HOBJECT_A_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
50367 }
50368 
50369 /*
50370  * Proxy helpers
50371  */
50372 
50373 #if defined(DUK_USE_ES6_PROXY)
50374 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hthread *thr, duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
50375  duk_tval *tv_target;
50376  duk_tval *tv_handler;
50377  duk_hobject *h_target;
50378  duk_hobject *h_handler;
50379 
50380  DUK_ASSERT(thr != NULL);
50381  DUK_ASSERT(obj != NULL);
50382  DUK_ASSERT(out_target != NULL);
50383  DUK_ASSERT(out_handler != NULL);
50384 
50385  /* Caller doesn't need to check exotic proxy behavior (but does so for
50386  * some fast paths).
50387  */
50388  if (DUK_LIKELY(!DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
50389  return 0;
50390  }
50391 
50392  tv_handler = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_HANDLER(thr));
50393  if (!tv_handler) {
50394  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REVOKED);
50395  return 0;
50396  }
50397  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_handler));
50398  h_handler = DUK_TVAL_GET_OBJECT(tv_handler);
50399  DUK_ASSERT(h_handler != NULL);
50400  *out_handler = h_handler;
50401  tv_handler = NULL; /* avoid issues with relocation */
50402 
50403  tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, obj, DUK_HTHREAD_STRING_INT_TARGET(thr));
50404  if (!tv_target) {
50405  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REVOKED);
50406  return 0;
50407  }
50408  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
50409  h_target = DUK_TVAL_GET_OBJECT(tv_target);
50410  DUK_ASSERT(h_target != NULL);
50411  *out_target = h_target;
50412  tv_target = NULL; /* avoid issues with relocation */
50413 
50414  return 1;
50415 }
50416 #endif /* DUK_USE_ES6_PROXY */
50417 
50418 /* Get Proxy target object. If the argument is not a Proxy, return it as is.
50419  * If a Proxy is revoked, an error is thrown.
50420  */
50421 #if defined(DUK_USE_ES6_PROXY)
50422 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hthread *thr, duk_hobject *obj) {
50423  duk_hobject *h_target;
50424  duk_hobject *h_handler;
50425 
50426  DUK_ASSERT(thr != NULL);
50427  DUK_ASSERT(obj != NULL);
50428 
50429  /* Resolve Proxy targets until Proxy chain ends. No explicit check for
50430  * a Proxy loop: user code cannot create such a loop without tweaking
50431  * internal properties directly.
50432  */
50433 
50434  while (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
50435  if (duk_hobject_proxy_check(thr, obj, &h_target, &h_handler)) {
50436  DUK_ASSERT(h_target != NULL);
50437  obj = h_target;
50438  } else {
50439  break;
50440  }
50441  }
50442 
50443  DUK_ASSERT(obj != NULL);
50444  return obj;
50445 }
50446 #endif /* DUK_USE_ES6_PROXY */
50447 
50448 #if defined(DUK_USE_ES6_PROXY)
50449 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) {
50450  duk_context *ctx = (duk_context *) thr;
50451  duk_hobject *h_handler;
50452 
50453  DUK_ASSERT(thr != NULL);
50454  DUK_ASSERT(obj != NULL);
50455  DUK_ASSERT(tv_key != NULL);
50456  DUK_ASSERT(out_target != NULL);
50457 
50458  if (!duk_hobject_proxy_check(thr, obj, out_target, &h_handler)) {
50459  return 0;
50460  }
50461  DUK_ASSERT(*out_target != NULL);
50462  DUK_ASSERT(h_handler != NULL);
50463 
50464  /* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
50465  * normal property set/get which would allow a proxy handler to interfere with
50466  * such behavior and to get access to internal key strings. This is not a problem
50467  * as such because internal key strings can be created in other ways too (e.g.
50468  * through buffers). The best fix is to change Duktape internal lookups to
50469  * skip proxy behavior. Until that, internal property accesses bypass the
50470  * proxy and are applied to the target (as if the handler did not exist).
50471  * This has some side effects, see test-bi-proxy-internal-keys.js.
50472  */
50473 
50474  if (DUK_TVAL_IS_STRING(tv_key)) {
50475  duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
50476  DUK_ASSERT(h_key != NULL);
50477  if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
50478  /* Symbol accesses must go through proxy lookup in ES2015.
50479  * Hidden symbols behave like Duktape 1.x internal keys
50480  * and currently won't.
50481  */
50482  DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
50483  return 0;
50484  }
50485  }
50486 
50487  /* The handler is looked up with a normal property lookup; it may be an
50488  * accessor or the handler object itself may be a proxy object. If the
50489  * handler is a proxy, we need to extend the valstack as we make a
50490  * recursive proxy check without a function call in between (in fact
50491  * there is no limit to the potential recursion here).
50492  *
50493  * (For sanity, proxy creation rejects another proxy object as either
50494  * the handler or the target at the moment so recursive proxy cases
50495  * are not realized now.)
50496  */
50497 
50498  /* XXX: C recursion limit if proxies are allowed as handler/target values */
50499 
50500  duk_require_stack(ctx, DUK__VALSTACK_PROXY_LOOKUP);
50501  duk_push_hobject(ctx, h_handler);
50502  if (duk_get_prop_stridx_short(ctx, -1, stridx_trap)) {
50503  /* -> [ ... handler trap ] */
50504  duk_insert(ctx, -2); /* -> [ ... trap handler ] */
50505 
50506  /* stack prepped for func call: [ ... trap handler ] */
50507  return 1;
50508  } else {
50509  duk_pop_2(ctx);
50510  return 0;
50511  }
50512 }
50513 #endif /* DUK_USE_ES6_PROXY */
50514 
50515 /*
50516  * Reallocate property allocation, moving properties to the new allocation.
50517  *
50518  * Includes key compaction, rehashing, and can also optionally abandoning
50519  * the array part, 'migrating' array entries into the beginning of the
50520  * new entry part. Arguments are not validated here, so e.g. new_h_size
50521  * MUST be a valid prime.
50522  *
50523  * There is no support for in-place reallocation or just compacting keys
50524  * without resizing the property allocation. This is intentional to keep
50525  * code size minimal.
50526  *
50527  * The implementation is relatively straightforward, except for the array
50528  * abandonment process. Array abandonment requires that new string keys
50529  * are interned, which may trigger GC. All keys interned so far must be
50530  * reachable for GC at all times; valstack is used for that now.
50531  *
50532  * Also, a GC triggered during this reallocation process must not interfere
50533  * with the object being resized. This is currently controlled by using
50534  * heap->mark_and_sweep_base_flags to indicate that no finalizers will be
50535  * executed (as they can affect ANY object) and no objects are compacted
50536  * (it would suffice to protect this particular object only, though).
50537  *
50538  * Note: a non-checked variant would be nice but is a bit tricky to
50539  * implement for the array abandonment process. It's easy for
50540  * everything else.
50541  *
50542  * Note: because we need to potentially resize the valstack (as part
50543  * of abandoning the array part), any tval pointers to the valstack
50544  * will become invalid after this call.
50545  */
50546 
50547 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
50548  duk_hobject *obj,
50549  duk_uint32_t new_e_size,
50550  duk_uint32_t new_a_size,
50551  duk_uint32_t new_h_size,
50552  duk_bool_t abandon_array) {
50553  duk_context *ctx = (duk_context *) thr;
50554  duk_small_uint_t prev_mark_and_sweep_base_flags;
50555  duk_uint32_t new_alloc_size;
50556  duk_uint32_t new_e_size_adjusted;
50557  duk_uint8_t *new_p;
50558  duk_hstring **new_e_k;
50559  duk_propvalue *new_e_pv;
50560  duk_uint8_t *new_e_f;
50561  duk_tval *new_a;
50562  duk_uint32_t *new_h;
50563  duk_uint32_t new_e_next;
50564  duk_uint_fast32_t i;
50565 
50566  DUK_ASSERT(thr != NULL);
50567  DUK_ASSERT(ctx != NULL);
50568  DUK_ASSERT(obj != NULL);
50569  DUK_ASSERT(!abandon_array || new_a_size == 0); /* if abandon_array, new_a_size must be 0 */
50570  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
50571  DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size); /* required to guarantee success of rehashing,
50572  * intentionally use unadjusted new_e_size
50573  */
50574  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
50575  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
50576 
50577  /*
50578  * Pre resize assertions.
50579  */
50580 
50581 #if defined(DUK_USE_ASSERTIONS)
50582  /* XXX: pre-checks (such as no duplicate keys) */
50583 #endif
50584 
50585  /*
50586  * For property layout 1, tweak e_size to ensure that the whole entry
50587  * part (key + val + flags) is a suitable multiple for alignment
50588  * (platform specific).
50589  *
50590  * Property layout 2 does not require this tweaking and is preferred
50591  * on low RAM platforms requiring alignment.
50592  */
50593 
50594 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
50595  DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
50596  new_e_size_adjusted = new_e_size;
50597 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
50598  DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
50599  new_e_size_adjusted = new_e_size;
50600 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
50601  new_e_size_adjusted = (new_e_size + DUK_HOBJECT_ALIGN_TARGET - 1) & (~(DUK_HOBJECT_ALIGN_TARGET - 1));
50602  DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
50603  (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
50604  DUK_ASSERT(new_e_size_adjusted >= new_e_size);
50605 #else
50606 #error invalid hobject layout defines
50607 #endif
50608 
50609  /*
50610  * Debug logging after adjustment.
50611  */
50612 
50613  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 "
50614  "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
50615  (void *) obj,
50616  (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
50617  DUK_HOBJECT_GET_ASIZE(obj),
50618  DUK_HOBJECT_GET_HSIZE(obj)),
50619  (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
50620  (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
50621  (long) DUK_HOBJECT_GET_ESIZE(obj),
50622  (long) DUK_HOBJECT_GET_ENEXT(obj),
50623  (long) DUK_HOBJECT_GET_ASIZE(obj),
50624  (long) DUK_HOBJECT_GET_HSIZE(obj),
50625  (long) new_e_size_adjusted,
50626  (long) new_a_size,
50627  (long) new_h_size,
50628  (long) abandon_array,
50629  (long) new_e_size));
50630 
50631  /*
50632  * Property count check. This is the only point where we ensure that
50633  * we don't get more (allocated) property space that we can handle.
50634  * There aren't hard limits as such, but some algorithms fail (e.g.
50635  * finding next higher prime, selecting hash part size) if we get too
50636  * close to the 4G property limit.
50637  *
50638  * Since this works based on allocation size (not actually used size),
50639  * the limit is a bit approximate but good enough in practice.
50640  */
50641 
50642  if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
50643  DUK_ERROR_ALLOC_FAILED(thr);
50644  }
50645 
50646  /*
50647  * Compute new alloc size and alloc new area.
50648  *
50649  * The new area is allocated as a dynamic buffer and placed into the
50650  * valstack for reachability. The actual buffer is then detached at
50651  * the end.
50652  *
50653  * Note: heap_mark_and_sweep_base_flags are altered here to ensure
50654  * no-one touches this object while we're resizing and rehashing it.
50655  * The flags must be reset on every exit path after it. Finalizers
50656  * and compaction is prevented currently for all objects while it
50657  * would be enough to restrict it only for the current object.
50658  */
50659 
50660  prev_mark_and_sweep_base_flags = thr->heap->mark_and_sweep_base_flags;
50661  thr->heap->mark_and_sweep_base_flags |=
50662  DUK_MS_FLAG_NO_FINALIZERS | /* avoid attempts to add/remove object keys */
50663  DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid attempt to compact the current object */
50664 
50665  new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
50666  DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
50667  if (new_alloc_size == 0) {
50668  /* for zero size, don't push anything on valstack */
50669  DUK_ASSERT(new_e_size_adjusted == 0);
50670  DUK_ASSERT(new_a_size == 0);
50671  DUK_ASSERT(new_h_size == 0);
50672  new_p = NULL;
50673  } else {
50674  /* This may trigger mark-and-sweep with arbitrary side effects,
50675  * including an attempted resize of the object we're resizing,
50676  * executing a finalizer which may add or remove properties of
50677  * the object we're resizing etc.
50678  */
50679 
50680  /* Note: buffer is dynamic so that we can 'steal' the actual
50681  * allocation later.
50682  */
50683 
50684  new_p = (duk_uint8_t *) duk_push_dynamic_buffer(ctx, new_alloc_size); /* errors out if out of memory */
50685  DUK_ASSERT(new_p != NULL); /* since new_alloc_size > 0 */
50686  }
50687 
50688  /* Set up pointers to the new property area: this is hidden behind a macro
50689  * because it is memory layout specific.
50690  */
50691  DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
50692  new_e_size_adjusted, new_a_size, new_h_size);
50693  DUK_UNREF(new_h); /* happens when hash part dropped */
50694  new_e_next = 0;
50695 
50696  /* if new_p == NULL, all of these pointers are NULL */
50697  DUK_ASSERT((new_p != NULL) ||
50698  (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
50699  new_a == NULL && new_h == NULL));
50700 
50701  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",
50702  (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
50703  (void *) new_a, (void *) new_h));
50704 
50705  /*
50706  * Migrate array to start of entries if requested.
50707  *
50708  * Note: from an enumeration perspective the order of entry keys matters.
50709  * Array keys should appear wherever they appeared before the array abandon
50710  * operation.
50711  */
50712 
50713  if (abandon_array) {
50714  /*
50715  * Note: assuming new_a_size == 0, and that entry part contains
50716  * no conflicting keys, refcounts do not need to be adjusted for
50717  * the values, as they remain exactly the same.
50718  *
50719  * The keys, however, need to be interned, incref'd, and be
50720  * reachable for GC. Any intern attempt may trigger a GC and
50721  * claim any non-reachable strings, so every key must be reachable
50722  * at all times.
50723  *
50724  * A longjmp must not occur here, as the new_p allocation would
50725  * be freed without these keys being decref'd, hence the messy
50726  * decref handling if intern fails.
50727  */
50728  DUK_ASSERT(new_a_size == 0);
50729 
50730  for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
50731  duk_tval *tv1;
50732  duk_tval *tv2;
50733  duk_hstring *key;
50734 
50735  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
50736 
50737  tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
50738  if (DUK_TVAL_IS_UNUSED(tv1)) {
50739  continue;
50740  }
50741 
50742  DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
50743  new_e_pv != NULL && new_e_f != NULL);
50744 
50745  /*
50746  * Intern key via the valstack to ensure reachability behaves
50747  * properly. We must avoid longjmp's here so use non-checked
50748  * primitives.
50749  *
50750  * Note: duk_check_stack() potentially reallocs the valstack,
50751  * invalidating any duk_tval pointers to valstack. Callers
50752  * must be careful.
50753  */
50754 
50755  /* never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which is generous */
50756  if (!duk_check_stack(ctx, 1)) {
50757  goto abandon_error;
50758  }
50759  DUK_ASSERT_VALSTACK_SPACE(thr, 1);
50760  key = duk_heap_string_intern_u32(thr->heap, i);
50761  if (!key) {
50762  goto abandon_error;
50763  }
50764  duk_push_hstring(ctx, key); /* keep key reachable for GC etc; guaranteed not to fail */
50765 
50766  /* key is now reachable in the valstack */
50767 
50768  DUK_HSTRING_INCREF(thr, key); /* second incref for the entry reference */
50769  new_e_k[new_e_next] = key;
50770  tv2 = &new_e_pv[new_e_next].v; /* array entries are all plain values */
50771  DUK_TVAL_SET_TVAL(tv2, tv1);
50772  new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
50773  DUK_PROPDESC_FLAG_ENUMERABLE |
50774  DUK_PROPDESC_FLAG_CONFIGURABLE;
50775  new_e_next++;
50776 
50777  /* Note: new_e_next matches pushed temp key count, and nothing can
50778  * fail above between the push and this point.
50779  */
50780  }
50781 
50782  DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
50783  duk_pop_n(ctx, new_e_next);
50784  }
50785 
50786  /*
50787  * Copy keys and values in the entry part (compacting them at the same time).
50788  */
50789 
50790  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
50791  duk_hstring *key;
50792 
50793  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
50794 
50795  key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
50796  if (!key) {
50797  continue;
50798  }
50799 
50800  DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
50801  new_e_pv != NULL && new_e_f != NULL);
50802 
50803  new_e_k[new_e_next] = key;
50804  new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
50805  new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
50806  new_e_next++;
50807  }
50808  /* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
50809 
50810  /*
50811  * Copy array elements to new array part.
50812  */
50813 
50814  if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
50815  /* copy existing entries as is */
50816  DUK_ASSERT(new_p != NULL && new_a != NULL);
50817  if (DUK_HOBJECT_GET_ASIZE(obj) > 0) {
50818  /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
50819  * the 'new_a' pointer will be invalid which is not allowed even
50820  * when copy size is zero.
50821  */
50822  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
50823  DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0);
50824  DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj));
50825  }
50826 
50827  /* fill new entries with -unused- (required, gc reachable) */
50828  for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
50829  duk_tval *tv = &new_a[i];
50830  DUK_TVAL_SET_UNUSED(tv);
50831  }
50832  } else {
50833 #if defined(DUK_USE_ASSERTIONS)
50834  /* caller must have decref'd values above new_a_size (if that is necessary) */
50835  if (!abandon_array) {
50836  for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
50837  duk_tval *tv;
50838  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
50839 
50840  /* current assertion is quite strong: decref's and set to unused */
50841  DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
50842  }
50843  }
50844 #endif
50845  if (new_a_size > 0) {
50846  /* Avoid zero copy with an invalid pointer. If obj->p is NULL,
50847  * the 'new_a' pointer will be invalid which is not allowed even
50848  * when copy size is zero.
50849  */
50850  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
50851  DUK_ASSERT(new_a_size > 0);
50852  DUK_MEMCPY((void *) new_a, (void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj), sizeof(duk_tval) * new_a_size);
50853  }
50854  }
50855 
50856  /*
50857  * Rebuild the hash part always from scratch (guaranteed to finish).
50858  *
50859  * Any resize of hash part requires rehashing. In addition, by rehashing
50860  * get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
50861  * to ensuring the hash part never fills up.
50862  */
50863 
50864 #if defined(DUK_USE_HOBJECT_HASH_PART)
50865  if (DUK_UNLIKELY(new_h_size > 0)) {
50866  DUK_ASSERT(new_h != NULL);
50867 
50868  /* fill new_h with u32 0xff = UNUSED */
50869  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
50870  DUK_ASSERT(new_h_size > 0);
50871  DUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
50872 
50873  DUK_ASSERT(new_e_next <= new_h_size); /* equality not actually possible */
50874  for (i = 0; i < new_e_next; i++) {
50875  duk_hstring *key = new_e_k[i];
50876  duk_uint32_t j, step;
50877 
50878  DUK_ASSERT(key != NULL);
50879  j = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size);
50880  step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
50881 
50882  for (;;) {
50883  DUK_ASSERT(new_h[j] != DUK__HASH_DELETED); /* should never happen */
50884  if (new_h[j] == DUK__HASH_UNUSED) {
50885  DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
50886  new_h[j] = i;
50887  break;
50888  }
50889  DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
50890  j = (j + step) % new_h_size;
50891 
50892  /* guaranteed to finish */
50893  DUK_ASSERT(j != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), new_h_size));
50894  }
50895  }
50896  } else {
50897  DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
50898  }
50899 #endif /* DUK_USE_HOBJECT_HASH_PART */
50900 
50901  /*
50902  * Nice debug log.
50903  */
50904 
50905  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 "
50906  "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
50907  (void *) obj,
50908  (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
50909  DUK_HOBJECT_GET_ASIZE(obj),
50910  DUK_HOBJECT_GET_HSIZE(obj)),
50911  (long) new_alloc_size,
50912  (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
50913  (long) DUK_HOBJECT_GET_ESIZE(obj),
50914  (long) DUK_HOBJECT_GET_ENEXT(obj),
50915  (long) DUK_HOBJECT_GET_ASIZE(obj),
50916  (long) DUK_HOBJECT_GET_HSIZE(obj),
50917  (void *) new_p,
50918  (long) new_e_size_adjusted,
50919  (long) new_e_next,
50920  (long) new_a_size,
50921  (long) new_h_size,
50922  (long) abandon_array,
50923  (long) new_e_size));
50924 
50925  /*
50926  * All done, switch properties ('p') allocation to new one.
50927  */
50928 
50929  DUK_FREE(thr->heap, DUK_HOBJECT_GET_PROPS(thr->heap, obj)); /* NULL obj->p is OK */
50930  DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
50931  DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
50932  DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
50933  DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
50934  DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
50935 
50936  if (new_p) {
50937  /*
50938  * Detach actual buffer from dynamic buffer in valstack, and
50939  * pop it from the stack.
50940  *
50941  * XXX: the buffer object is certainly not reachable at this point,
50942  * so it would be nice to free it forcibly even with only
50943  * mark-and-sweep enabled. Not a big issue though.
50944  */
50945  (void) duk_steal_buffer(ctx, -1, NULL);
50946  duk_pop(ctx);
50947  } else {
50948  DUK_ASSERT(new_alloc_size == 0);
50949  /* no need to pop, nothing was pushed */
50950  }
50951 
50952  /* clear array part flag only after switching */
50953  if (abandon_array) {
50954  DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
50955  }
50956 
50957  DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
50958 
50959  thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
50960 
50961  /*
50962  * Post resize assertions.
50963  */
50964 
50965 #if defined(DUK_USE_ASSERTIONS)
50966  /* XXX: post-checks (such as no duplicate keys) */
50967 #endif
50968  return;
50969 
50970  /*
50971  * Abandon array failed, need to decref keys already inserted
50972  * into the beginning of new_e_k before unwinding valstack.
50973  */
50974 
50975  abandon_error:
50976  DUK_D(DUK_DPRINT("hobject resize failed during abandon array, decref keys"));
50977  i = new_e_next;
50978  while (i > 0) {
50979  i--;
50980  DUK_ASSERT(new_e_k != NULL);
50981  DUK_ASSERT(new_e_k[i] != NULL);
50982  DUK_HSTRING_DECREF(thr, new_e_k[i]); /* side effects */
50983  }
50984 
50985  thr->heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
50986 
50987  DUK_ERROR_ALLOC_FAILED(thr);
50988 }
50989 
50990 /*
50991  * Helpers to resize properties allocation on specific needs.
50992  */
50993 
50994 /* Grow entry part allocation for one additional entry. */
50995 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
50996  duk_uint32_t old_e_used; /* actually used, non-NULL entries */
50997  duk_uint32_t new_e_size;
50998  duk_uint32_t new_a_size;
50999  duk_uint32_t new_h_size;
51000 
51001  DUK_ASSERT(thr != NULL);
51002  DUK_ASSERT(obj != NULL);
51003 
51004  /* Duktape 0.11.0 and prior tried to optimize the resize by not
51005  * counting the number of actually used keys prior to the resize.
51006  * This worked mostly well but also caused weird leak-like behavior
51007  * as in: test-bug-object-prop-alloc-unbounded.js. So, now we count
51008  * the keys explicitly to compute the new entry part size.
51009  */
51010 
51011  old_e_used = duk__count_used_e_keys(thr, obj);
51012  new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
51013 #if defined(DUK_USE_HOBJECT_HASH_PART)
51014  new_h_size = duk__get_default_h_size(new_e_size);
51015 #else
51016  new_h_size = 0;
51017 #endif
51018  new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
51019  DUK_ASSERT(new_e_size >= old_e_used + 1); /* duk__get_min_grow_e() is always >= 1 */
51020 
51021  duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
51022 }
51023 
51024 /* Grow array part for a new highest array index. */
51025 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
51026  duk_uint32_t new_e_size;
51027  duk_uint32_t new_a_size;
51028  duk_uint32_t new_h_size;
51029 
51030  DUK_ASSERT(thr != NULL);
51031  DUK_ASSERT(obj != NULL);
51032  DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
51033 
51034  /* minimum new length is highest_arr_idx + 1 */
51035 
51036  new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
51037  new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
51038  new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
51039  DUK_ASSERT(new_a_size >= highest_arr_idx + 1); /* duk__get_min_grow_a() is always >= 1 */
51040 
51041  duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
51042 }
51043 
51044 /* Abandon array part, moving array entries into entries part.
51045  * This requires a props resize, which is a heavy operation.
51046  * We also compact the entries part while we're at it, although
51047  * this is not strictly required.
51048  */
51049 DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
51050  duk_uint32_t new_e_size;
51051  duk_uint32_t new_a_size;
51052  duk_uint32_t new_h_size;
51053  duk_uint32_t e_used; /* actually used, non-NULL keys */
51054  duk_uint32_t a_used;
51055  duk_uint32_t a_size;
51056 
51057  DUK_ASSERT(thr != NULL);
51058  DUK_ASSERT(obj != NULL);
51059 
51060  e_used = duk__count_used_e_keys(thr, obj);
51061  duk__compute_a_stats(thr, obj, &a_used, &a_size);
51062 
51063  /*
51064  * Must guarantee all actually used array entries will fit into
51065  * new entry part. Add one growth step to ensure we don't run out
51066  * of space right away.
51067  */
51068 
51069  new_e_size = e_used + a_used;
51070  new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
51071  new_a_size = 0;
51072 #if defined(DUK_USE_HOBJECT_HASH_PART)
51073  new_h_size = duk__get_default_h_size(new_e_size);
51074 #else
51075  new_h_size = 0;
51076 #endif
51077 
51078  DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
51079  "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
51080  "resize to e_size=%ld, a_size=%ld, h_size=%ld",
51081  (void *) obj, (long) e_used, (long) a_used, (long) a_size,
51082  (long) new_e_size, (long) new_a_size, (long) new_h_size));
51083 
51084  duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
51085 }
51086 
51087 /*
51088  * Compact an object. Minimizes allocation size for objects which are
51089  * not likely to be extended. This is useful for internal and non-
51090  * extensible objects, but can also be called for non-extensible objects.
51091  * May abandon the array part if it is computed to be too sparse.
51092  *
51093  * This call is relatively expensive, as it needs to scan both the
51094  * entries and the array part.
51095  *
51096  * The call may fail due to allocation error.
51097  */
51098 
51099 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
51100  duk_uint32_t e_size; /* currently used -> new size */
51101  duk_uint32_t a_size; /* currently required */
51102  duk_uint32_t a_used; /* actually used */
51103  duk_uint32_t h_size;
51104  duk_bool_t abandon_array;
51105 
51106  DUK_ASSERT(thr != NULL);
51107  DUK_ASSERT(obj != NULL);
51108 
51109 #if defined(DUK_USE_ROM_OBJECTS)
51110  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
51111  DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
51112  return;
51113  }
51114 #endif
51115 
51116  e_size = duk__count_used_e_keys(thr, obj);
51117  duk__compute_a_stats(thr, obj, &a_used, &a_size);
51118 
51119  DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
51120  "resized array density would be: %ld/%ld = %lf",
51121  (long) e_size, (long) a_used, (long) a_size,
51122  (long) a_used, (long) a_size,
51123  (double) a_used / (double) a_size));
51124 
51125  if (duk__abandon_array_density_check(a_used, a_size)) {
51126  DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
51127  (long) a_used, (long) a_size));
51128  abandon_array = 1;
51129  e_size += a_used;
51130  a_size = 0;
51131  } else {
51132  DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
51133  abandon_array = 0;
51134  }
51135 
51136 #if defined(DUK_USE_HOBJECT_HASH_PART)
51137  if (e_size >= DUK_HOBJECT_E_USE_HASH_LIMIT) {
51138  h_size = duk__get_default_h_size(e_size);
51139  } else {
51140  h_size = 0;
51141  }
51142 #else
51143  h_size = 0;
51144 #endif
51145 
51146  DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
51147  (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
51148 
51149  duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
51150 }
51151 
51152 /*
51153  * Find an existing key from entry part either by linear scan or by
51154  * using the hash index (if it exists).
51155  *
51156  * Sets entry index (and possibly the hash index) to output variables,
51157  * which allows the caller to update the entry and hash entries in-place.
51158  * If entry is not found, both values are set to -1. If entry is found
51159  * but there is no hash part, h_idx is set to -1.
51160  */
51161 
51162 DUK_INTERNAL 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) {
51163  DUK_ASSERT(obj != NULL);
51164  DUK_ASSERT(key != NULL);
51165  DUK_ASSERT(e_idx != NULL);
51166  DUK_ASSERT(h_idx != NULL);
51167  DUK_UNREF(heap);
51168 
51169  if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
51170  {
51171  /* Linear scan: more likely because most objects are small.
51172  * This is an important fast path.
51173  *
51174  * XXX: this might be worth inlining for property lookups.
51175  */
51176  duk_uint_fast32_t i;
51177  duk_uint_fast32_t n;
51178  duk_hstring **h_keys_base;
51179  DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
51180 
51181  h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
51182  n = DUK_HOBJECT_GET_ENEXT(obj);
51183  for (i = 0; i < n; i++) {
51184  if (h_keys_base[i] == key) {
51185  *e_idx = i;
51186  *h_idx = -1;
51187  return;
51188  }
51189  }
51190  }
51191 #if defined(DUK_USE_HOBJECT_HASH_PART)
51192  else
51193  {
51194  /* hash lookup */
51195  duk_uint32_t n;
51196  duk_uint32_t i, step;
51197  duk_uint32_t *h_base;
51198 
51199  DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
51200 
51201  h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
51202  n = DUK_HOBJECT_GET_HSIZE(obj);
51203  i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
51204  step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
51205 
51206  for (;;) {
51207  duk_uint32_t t;
51208 
51209  DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
51210  DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
51211  t = h_base[i];
51212  DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
51213  (t < DUK_HOBJECT_GET_ESIZE(obj))); /* t >= 0 always true, unsigned */
51214 
51215  if (t == DUK__HASH_UNUSED) {
51216  break;
51217  } else if (t == DUK__HASH_DELETED) {
51218  DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
51219  (long) i, (long) t));
51220  } else {
51221  DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
51222  if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
51223  DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
51224  (long) i, (long) t, (void *) key));
51225  *e_idx = t;
51226  *h_idx = i;
51227  return;
51228  }
51229  DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
51230  (long) i, (long) t));
51231  }
51232  i = (i + step) % n;
51233 
51234  /* guaranteed to finish, as hash is never full */
51235  DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n));
51236  }
51237  }
51238 #endif /* DUK_USE_HOBJECT_HASH_PART */
51239 
51240  /* not found */
51241  *e_idx = -1;
51242  *h_idx = -1;
51243 }
51244 
51245 /* For internal use: get non-accessor entry value */
51246 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
51247  duk_int_t e_idx;
51248  duk_int_t h_idx;
51249 
51250  DUK_ASSERT(obj != NULL);
51251  DUK_ASSERT(key != NULL);
51252  DUK_UNREF(heap);
51253 
51254  duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
51255  if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
51256  return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
51257  } else {
51258  return NULL;
51259  }
51260 }
51261 
51262 /* For internal use: get non-accessor entry value and attributes */
51263 DUK_INTERNAL 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) {
51264  duk_int_t e_idx;
51265  duk_int_t h_idx;
51266 
51267  DUK_ASSERT(obj != NULL);
51268  DUK_ASSERT(key != NULL);
51269  DUK_ASSERT(out_attrs != NULL);
51270  DUK_UNREF(heap);
51271 
51272  duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx);
51273  if (e_idx >= 0 && !DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
51274  *out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
51275  return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
51276  } else {
51277  *out_attrs = 0;
51278  return NULL;
51279  }
51280 }
51281 
51282 /* For internal use: get array part value */
51283 DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
51284  duk_tval *tv;
51285 
51286  DUK_ASSERT(obj != NULL);
51287  DUK_UNREF(heap);
51288 
51289  if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
51290  return NULL;
51291  }
51292  if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
51293  return NULL;
51294  }
51295  tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
51296  return tv;
51297 }
51298 
51299 /*
51300  * Allocate and initialize a new entry, resizing the properties allocation
51301  * if necessary. Returns entry index (e_idx) or throws an error if alloc fails.
51302  *
51303  * Sets the key of the entry (increasing the key's refcount), and updates
51304  * the hash part if it exists. Caller must set value and flags, and update
51305  * the entry value refcount. A decref for the previous value is not necessary.
51306  */
51307 
51308 DUK_LOCAL duk_bool_t duk__alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
51309  duk_uint32_t idx;
51310 
51311  DUK_ASSERT(thr != NULL);
51312  DUK_ASSERT(obj != NULL);
51313  DUK_ASSERT(key != NULL);
51314  DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
51315 
51316 #if defined(DUK_USE_ASSERTIONS)
51317  /* key must not already exist in entry part */
51318  {
51319  duk_uint_fast32_t i;
51320  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
51321  DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
51322  }
51323  }
51324 #endif
51325 
51326  if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
51327  /* only need to guarantee 1 more slot, but allocation growth is in chunks */
51328  DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
51329  duk__grow_props_for_new_entry_item(thr, obj);
51330  }
51331  DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
51332  idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
51333 
51334  /* previous value is assumed to be garbage, so don't touch it */
51335  DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
51336  DUK_HSTRING_INCREF(thr, key);
51337 
51338 #if defined(DUK_USE_HOBJECT_HASH_PART)
51339  if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
51340  duk_uint32_t n;
51341  duk_uint32_t i, step;
51342  duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
51343 
51344  n = DUK_HOBJECT_GET_HSIZE(obj);
51345  i = DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), n);
51346  step = DUK__HASH_PROBE_STEP(DUK_HSTRING_GET_HASH(key));
51347 
51348  for (;;) {
51349  duk_uint32_t t = h_base[i];
51350  if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
51351  DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() inserted key into hash part, %ld -> %ld",
51352  (long) i, (long) idx));
51353  DUK_ASSERT_DISABLE(i >= 0); /* unsigned */
51354  DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
51355  DUK_ASSERT_DISABLE(idx >= 0);
51356  DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
51357  h_base[i] = idx;
51358  break;
51359  }
51360  DUK_DDD(DUK_DDDPRINT("duk__alloc_entry_checked() miss %ld", (long) i));
51361  i = (i + step) % n;
51362 
51363  /* guaranteed to find an empty slot */
51364  DUK_ASSERT(i != (duk_uint32_t) DUK__HASH_INITIAL(DUK_HSTRING_GET_HASH(key), DUK_HOBJECT_GET_HSIZE(obj)));
51365  }
51366  }
51367 #endif /* DUK_USE_HOBJECT_HASH_PART */
51368 
51369  /* Note: we could return the hash index here too, but it's not
51370  * needed right now.
51371  */
51372 
51373  DUK_ASSERT_DISABLE(idx >= 0);
51374  DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
51375  DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
51376  return idx;
51377 }
51378 
51379 /*
51380  * Object internal value
51381  *
51382  * Returned value is guaranteed to be reachable / incref'd, caller does not need
51383  * to incref OR decref. No proxies or accessors are invoked, no prototype walk.
51384  */
51385 
51386 DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
51387  duk_int_t e_idx;
51388  duk_int_t h_idx;
51389 
51390  DUK_ASSERT(heap != NULL);
51391  DUK_ASSERT(obj != NULL);
51392  DUK_ASSERT(tv_out != NULL);
51393 
51394  /* always in entry part, no need to look up parents etc */
51395  duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx);
51396  if (e_idx >= 0) {
51397  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
51398  DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
51399  return 1;
51400  }
51401  DUK_TVAL_SET_UNDEFINED(tv_out);
51402  return 0;
51403 }
51404 
51405 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
51406  duk_tval tv;
51407 
51408  DUK_ASSERT(heap != NULL);
51409  DUK_ASSERT(obj != NULL);
51410 
51411  /* This is not strictly necessary, but avoids compiler warnings; e.g.
51412  * gcc won't reliably detect that no uninitialized data is read below.
51413  */
51414  DUK_MEMZERO((void *) &tv, sizeof(duk_tval));
51415 
51416  if (duk_hobject_get_internal_value(heap, obj, &tv)) {
51417  duk_hstring *h;
51418  DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
51419  h = DUK_TVAL_GET_STRING(&tv);
51420  /* No explicit check for string vs. symbol, accept both. */
51421  return h;
51422  }
51423 
51424  return NULL;
51425 }
51426 
51427 /*
51428  * Arguments handling helpers (argument map mainly).
51429  *
51430  * An arguments object has exotic behavior for some numeric indices.
51431  * Accesses may translate to identifier operations which may have
51432  * arbitrary side effects (potentially invalidating any duk_tval
51433  * pointers).
51434  */
51435 
51436 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
51437  * if mapped, and leave the result on top of stack (and return non-zero).
51438  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
51439  */
51440 DUK_LOCAL
51441 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
51442  duk_hobject *obj,
51443  duk_hstring *key,
51444  duk_propdesc *temp_desc,
51445  duk_hobject **out_map,
51446  duk_hobject **out_varenv) {
51447  duk_context *ctx = (duk_context *) thr;
51448  duk_hobject *map;
51449  duk_hobject *varenv;
51450  duk_bool_t rc;
51451 
51452  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51453 
51454  DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
51455  "(obj -> %!O, key -> %!O)",
51456  (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
51457  (duk_heaphdr *) obj, (duk_heaphdr *) key));
51458 
51459  if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
51460  DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
51461  return 0;
51462  }
51463 
51464  map = duk_require_hobject(ctx, -1);
51465  DUK_ASSERT(map != NULL);
51466  duk_pop(ctx); /* map is reachable through obj */
51467 
51468  if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
51469  DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
51470  return 0;
51471  }
51472 
51473  /* [... varname] */
51474  DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
51475  (duk_tval *) duk_get_tval(ctx, -1)));
51476  DUK_ASSERT(duk_is_string(ctx, -1)); /* guaranteed when building arguments */
51477 
51478  /* get varenv for varname (callee's declarative lexical environment) */
51479  rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
51480  DUK_UNREF(rc);
51481  DUK_ASSERT(rc != 0); /* arguments MUST have an initialized lexical environment reference */
51482  varenv = duk_require_hobject(ctx, -1);
51483  DUK_ASSERT(varenv != NULL);
51484  duk_pop(ctx); /* varenv remains reachable through 'obj' */
51485 
51486  DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
51487 
51488  /* success: leave varname in stack */
51489  *out_map = map;
51490  *out_varenv = varenv;
51491  return 1; /* [... varname] */
51492 }
51493 
51494 /* Lookup 'key' from arguments internal 'map', and leave replacement value
51495  * on stack top if mapped (and return non-zero).
51496  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
51497  */
51498 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
51499  duk_context *ctx = (duk_context *) thr;
51500  duk_hobject *map;
51501  duk_hobject *varenv;
51502  duk_hstring *varname;
51503 
51504  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51505 
51506  if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
51507  DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
51508  return 0;
51509  }
51510 
51511  /* [... varname] */
51512 
51513  varname = duk_require_hstring(ctx, -1);
51514  DUK_ASSERT(varname != NULL);
51515  duk_pop(ctx); /* varname is still reachable */
51516 
51517  DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
51518  "key=%!O, varname=%!O",
51519  (duk_heaphdr *) key,
51520  (duk_heaphdr *) varname));
51521 
51522  (void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
51523 
51524  /* [... value this_binding] */
51525 
51526  duk_pop(ctx);
51527 
51528  /* leave result on stack top */
51529  return 1;
51530 }
51531 
51532 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
51533  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
51534  * Assumes stack top contains 'put' value (which is NOT popped).
51535  */
51536 DUK_LOCAL 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) {
51537  duk_context *ctx = (duk_context *) thr;
51538  duk_hobject *map;
51539  duk_hobject *varenv;
51540  duk_hstring *varname;
51541 
51542  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51543 
51544  if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
51545  DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
51546  return;
51547  }
51548 
51549  /* [... put_value varname] */
51550 
51551  varname = duk_require_hstring(ctx, -1);
51552  DUK_ASSERT(varname != NULL);
51553  duk_pop(ctx); /* varname is still reachable */
51554 
51555  DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
51556  "key=%!O, varname=%!O, value=%!T",
51557  (duk_heaphdr *) key,
51558  (duk_heaphdr *) varname,
51559  (duk_tval *) duk_require_tval(ctx, -1)));
51560 
51561  /* [... put_value] */
51562 
51563  /*
51564  * Note: although arguments object variable mappings are only established
51565  * for non-strict functions (and a call to a non-strict function created
51566  * the arguments object in question), an inner strict function may be doing
51567  * the actual property write. Hence the throw_flag applied here comes from
51568  * the property write call.
51569  */
51570 
51571  duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, -1), throw_flag);
51572 
51573  /* [... put_value] */
51574 }
51575 
51576 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
51577  * Used in E5 Section 10.6 algorithm for [[Delete]]. Note that the
51578  * variable/argument itself (where the map points) is not deleted.
51579  */
51580 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
51581  duk_context *ctx = (duk_context *) thr;
51582  duk_hobject *map;
51583 
51584  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51585 
51586  if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
51587  DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
51588  return;
51589  }
51590 
51591  map = duk_require_hobject(ctx, -1);
51592  DUK_ASSERT(map != NULL);
51593  duk_pop(ctx); /* map is reachable through obj */
51594 
51595  DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
51596  (duk_heaphdr *) key));
51597 
51598  /* Note: no recursion issue, we can trust 'map' to behave */
51599  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
51600  DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
51601  (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
51602  DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
51603 }
51604 
51605 /*
51606  * Ecmascript compliant [[GetOwnProperty]](P), for internal use only.
51607  *
51608  * If property is found:
51609  * - Fills descriptor fields to 'out_desc'
51610  * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
51611  * property onto the stack ('undefined' for accessor properties).
51612  * - Returns non-zero
51613  *
51614  * If property is not found:
51615  * - 'out_desc' is left in untouched state (possibly garbage)
51616  * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
51617  * set)
51618  * - Returns zero
51619  *
51620  * Notes:
51621  *
51622  * - Getting a property descriptor may cause an allocation (and hence
51623  * GC) to take place, hence reachability and refcount of all related
51624  * values matter. Reallocation of value stack, properties, etc may
51625  * invalidate many duk_tval pointers (concretely, those which reside
51626  * in memory areas subject to reallocation). However, heap object
51627  * pointers are never affected (heap objects have stable pointers).
51628  *
51629  * - The value of a plain property is always reachable and has a non-zero
51630  * reference count.
51631  *
51632  * - The value of a virtual property is not necessarily reachable from
51633  * elsewhere and may have a refcount of zero. Hence we push it onto
51634  * the valstack for the caller, which ensures it remains reachable
51635  * while it is needed.
51636  *
51637  * - There are no virtual accessor properties. Hence, all getters and
51638  * setters are always related to concretely stored properties, which
51639  * ensures that the get/set functions in the resulting descriptor are
51640  * reachable and have non-zero refcounts. Should there be virtual
51641  * accessor properties later, this would need to change.
51642  */
51643 
51644 DUK_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) {
51645  duk_context *ctx = (duk_context *) thr;
51646  duk_tval *tv;
51647 
51648  DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
51649  "arr_idx=%ld (obj -> %!O, key -> %!O)",
51650  (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
51651  (long) flags, (long) arr_idx,
51652  (duk_heaphdr *) obj, (duk_heaphdr *) key));
51653 
51654  DUK_ASSERT(ctx != NULL);
51655  DUK_ASSERT(thr != NULL);
51656  DUK_ASSERT(thr->heap != NULL);
51657  DUK_ASSERT(obj != NULL);
51658  DUK_ASSERT(key != NULL);
51659  DUK_ASSERT(out_desc != NULL);
51660  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51661 
51662  /* XXX: optimize this filling behavior later */
51663  out_desc->flags = 0;
51664  out_desc->get = NULL;
51665  out_desc->set = NULL;
51666  out_desc->e_idx = -1;
51667  out_desc->h_idx = -1;
51668  out_desc->a_idx = -1;
51669 
51670  /*
51671  * Array part
51672  */
51673 
51674  if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
51675  if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
51676  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
51677  if (!DUK_TVAL_IS_UNUSED(tv)) {
51678  DUK_DDD(DUK_DDDPRINT("-> found in array part"));
51679  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51680  duk_push_tval(ctx, tv);
51681  }
51682  /* implicit attributes */
51683  out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
51684  DUK_PROPDESC_FLAG_CONFIGURABLE |
51685  DUK_PROPDESC_FLAG_ENUMERABLE;
51686  out_desc->a_idx = arr_idx;
51687  goto prop_found;
51688  }
51689  }
51690  /* assume array part is comprehensive (contains all array indexed elements
51691  * or none of them); hence no need to check the entries part here.
51692  */
51693  DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property (has array part, "
51694  "should be there if present)"));
51695  goto prop_not_found_concrete;
51696  }
51697 
51698  /*
51699  * Entries part
51700  */
51701 
51702  duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx);
51703  if (out_desc->e_idx >= 0) {
51704  duk_int_t e_idx = out_desc->e_idx;
51705  out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
51706  if (out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR) {
51707  DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
51708  out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
51709  out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
51710  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51711  /* a dummy undefined value is pushed to make valstack
51712  * behavior uniform for caller
51713  */
51714  duk_push_undefined(ctx);
51715  }
51716  } else {
51717  DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
51718  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
51719  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51720  duk_push_tval(ctx, tv);
51721  }
51722  }
51723  goto prop_found;
51724  }
51725 
51726  /*
51727  * Not found as a concrete property, check for virtual properties.
51728  */
51729 
51730  prop_not_found_concrete:
51731 
51732  if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
51733  /* Quick skip. */
51734  goto prop_not_found;
51735  }
51736 
51737  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
51738  duk_harray *a;
51739 
51740  DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
51741  (duk_heaphdr *) key, (long) arr_idx));
51742 
51743  a = (duk_harray *) obj;
51744  DUK_ASSERT_HARRAY_VALID(a);
51745 
51746  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51747  DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
51748 
51749  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51750  duk_push_uint(ctx, (duk_uint_t) a->length);
51751  }
51752  out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
51753  if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
51754  out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
51755  }
51756 
51757  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51758  return 1; /* cannot be arguments exotic */
51759  }
51760  } else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
51761  DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
51762  (duk_heaphdr *) key, (long) arr_idx));
51763 
51764  if (arr_idx != DUK__NO_ARRAY_INDEX) {
51765  duk_hstring *h_val;
51766 
51767  DUK_DDD(DUK_DDDPRINT("array index exists"));
51768 
51769  h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
51770  DUK_ASSERT(h_val);
51771  if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
51772  DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
51773  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51774  duk_push_hstring(ctx, h_val);
51775  duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
51776  }
51777  out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE | /* E5 Section 15.5.5.2 */
51778  DUK_PROPDESC_FLAG_VIRTUAL;
51779 
51780  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51781  return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
51782  } else {
51783  /* index is above internal string length -> property is fully normal */
51784  DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
51785  }
51786  } else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51787  duk_hstring *h_val;
51788 
51789  DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
51790 
51791  h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
51792  DUK_ASSERT(h_val != NULL);
51793  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51794  duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
51795  }
51796  out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* E5 Section 15.5.5.1 */
51797 
51798  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51799  return 1; /* cannot be arguments exotic */
51800  }
51801  }
51802 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
51803  else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
51804  duk_hbufobj *h_bufobj;
51805  duk_uint_t byte_off;
51806  duk_small_uint_t elem_size;
51807 
51808  h_bufobj = (duk_hbufobj *) obj;
51809  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
51810  DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
51811  (duk_heaphdr *) key, (long) arr_idx));
51812 
51813  if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
51814  DUK_DDD(DUK_DDDPRINT("array index exists"));
51815 
51816  /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
51817  * length downshift won't.
51818  */
51819  if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
51820  byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
51821  elem_size = 1 << h_bufobj->shift;
51822  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51823  duk_uint8_t *data;
51824 
51825  if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
51826  data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
51827  duk_hbufobj_push_validated_read(ctx, h_bufobj, data, elem_size);
51828  } else {
51829  DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
51830  duk_push_uint(ctx, 0);
51831  }
51832  }
51833  out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
51834  DUK_PROPDESC_FLAG_VIRTUAL;
51835  if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
51836  /* ArrayBuffer indices are non-standard and are
51837  * non-enumerable to avoid their serialization.
51838  */
51839  out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
51840  }
51841 
51842  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51843  return 1; /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
51844  } else {
51845  /* index is above internal buffer length -> property is fully normal */
51846  DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
51847  }
51848  } else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
51849  DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
51850 
51851  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51852  /* Length in elements: take into account shift, but
51853  * intentionally don't check the underlying buffer here.
51854  */
51855  duk_push_uint(ctx, h_bufobj->length >> h_bufobj->shift);
51856  }
51857  out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
51858 
51859  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51860  return 1; /* cannot be arguments exotic */
51861  }
51862  }
51863 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
51864  else if (DUK_HOBJECT_HAS_EXOTIC_DUKFUNC(obj)) {
51865  DUK_DDD(DUK_DDDPRINT("duktape/c object exotic property get for key: %!O, arr_idx: %ld",
51866  (duk_heaphdr *) key, (long) arr_idx));
51867 
51868  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
51869  DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
51870 
51871  if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
51872  duk_int16_t func_nargs = ((duk_hnatfunc *) obj)->nargs;
51873  duk_push_int(ctx, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
51874  }
51875  out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL; /* not enumerable */
51876 
51877  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
51878  return 1; /* cannot be arguments exotic */
51879  }
51880  }
51881 
51882  /* Array properties have exotic behavior but they are concrete,
51883  * so no special handling here.
51884  *
51885  * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
51886  * is only relevant as a post-check implemented below; hence no
51887  * check here.
51888  */
51889 
51890  /*
51891  * Not found as concrete or virtual
51892  */
51893 
51894  prop_not_found:
51895  DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
51896  return 0;
51897 
51898  /*
51899  * Found
51900  *
51901  * Arguments object has exotic post-processing, see E5 Section 10.6,
51902  * description of [[GetOwnProperty]] variant for arguments.
51903  */
51904 
51905  prop_found:
51906  DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
51907 
51908  /* Notes:
51909  * - only numbered indices are relevant, so arr_idx fast reject is good
51910  * (this is valid unless there are more than 4**32-1 arguments).
51911  * - since variable lookup has no side effects, this can be skipped if
51912  * DUK_GETDESC_FLAG_PUSH_VALUE is not set.
51913  */
51914 
51915  if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
51916  arr_idx != DUK__NO_ARRAY_INDEX &&
51917  (flags & DUK_GETDESC_FLAG_PUSH_VALUE)) {
51918  duk_propdesc temp_desc;
51919 
51920  /* Magically bound variable cannot be an accessor. However,
51921  * there may be an accessor property (or a plain property) in
51922  * place with magic behavior removed. This happens e.g. when
51923  * a magic property is redefined with defineProperty().
51924  * Cannot assert for "not accessor" here.
51925  */
51926 
51927  /* replaces top of stack with new value if necessary */
51928  DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
51929 
51930  /* This can perform a variable lookup but only into a declarative
51931  * environment which has no side effects.
51932  */
51933  if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
51934  DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
51935  (duk_tval *) duk_get_tval(ctx, -2),
51936  (duk_tval *) duk_get_tval(ctx, -1)));
51937  /* [... old_result result] -> [... result] */
51938  duk_remove_m2(ctx);
51939  }
51940  }
51941 
51942  return 1;
51943 }
51944 
51945 DUK_INTERNAL 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) {
51946  DUK_ASSERT(thr != NULL);
51947  DUK_ASSERT(obj != NULL);
51948  DUK_ASSERT(key != NULL);
51949  DUK_ASSERT(out_desc != NULL);
51950  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51951 
51952  return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
51953 }
51954 
51955 /*
51956  * Ecmascript compliant [[GetProperty]](P), for internal use only.
51957  *
51958  * If property is found:
51959  * - Fills descriptor fields to 'out_desc'
51960  * - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
51961  * property onto the stack ('undefined' for accessor properties).
51962  * - Returns non-zero
51963  *
51964  * If property is not found:
51965  * - 'out_desc' is left in untouched state (possibly garbage)
51966  * - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
51967  * set)
51968  * - Returns zero
51969  *
51970  * May cause arbitrary side effects and invalidate (most) duk_tval
51971  * pointers.
51972  */
51973 
51974 DUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {
51975  duk_hobject *curr;
51976  duk_uint32_t arr_idx;
51977  duk_uint_t sanity;
51978 
51979  DUK_ASSERT(thr != NULL);
51980  DUK_ASSERT(thr->heap != NULL);
51981  DUK_ASSERT(obj != NULL);
51982  DUK_ASSERT(key != NULL);
51983  DUK_ASSERT(out_desc != NULL);
51984  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
51985 
51986  arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
51987 
51988  DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
51989  "arr_idx=%ld (obj -> %!O, key -> %!O)",
51990  (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
51991  (long) flags, (long) arr_idx,
51992  (duk_heaphdr *) obj, (duk_heaphdr *) key));
51993 
51994  curr = obj;
51995  DUK_ASSERT(curr != NULL);
51996  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
51997  do {
51998  if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
51999  /* stack contains value (if requested), 'out_desc' is set */
52000  return 1;
52001  }
52002 
52003  /* not found in 'curr', next in prototype chain; impose max depth */
52004  if (sanity-- == 0) {
52005  if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
52006  /* treat like property not found */
52007  break;
52008  } else {
52009  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
52010  }
52011  }
52012  curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
52013  } while (curr);
52014 
52015  /* out_desc is left untouched (possibly garbage), caller must use return
52016  * value to determine whether out_desc can be looked up
52017  */
52018 
52019  return 0;
52020 }
52021 
52022 /*
52023  * Shallow fast path checks for accessing array elements with numeric
52024  * indices. The goal is to try to avoid coercing an array index to an
52025  * (interned) string for the most common lookups, in particular, for
52026  * standard Array objects.
52027  *
52028  * Interning is avoided but only for a very narrow set of cases:
52029  * - Object has array part, index is within array allocation, and
52030  * value is not unused (= key exists)
52031  * - Object has no interfering exotic behavior (e.g. arguments or
52032  * string object exotic behaviors interfere, array exotic
52033  * behavior does not).
52034  *
52035  * Current shortcoming: if key does not exist (even if it is within
52036  * the array allocation range) a slow path lookup with interning is
52037  * always required. This can probably be fixed so that there is a
52038  * quick fast path for non-existent elements as well, at least for
52039  * standard Array objects.
52040  */
52041 
52042 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
52043 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
52044  duk_tval *tv;
52045  duk_uint32_t idx;
52046 
52047  DUK_UNREF(thr);
52048 
52049  if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
52050  !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
52051  !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
52052  !DUK_HOBJECT_IS_BUFOBJ(obj) &&
52053  !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
52054  /* Must have array part and no conflicting exotic behaviors.
52055  * Doesn't need to have array special behavior, e.g. Arguments
52056  * object has array part.
52057  */
52058  return NULL;
52059  }
52060 
52061  /* Arrays never have other exotic behaviors. */
52062 
52063  DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
52064  "behavior, object has array part)"));
52065 
52066 #if defined(DUK_USE_FASTINT)
52067  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52068  idx = duk__tval_fastint_to_arr_idx(tv_key);
52069  } else
52070 #endif
52071  if (DUK_TVAL_IS_DOUBLE(tv_key)) {
52072  idx = duk__tval_number_to_arr_idx(tv_key);
52073  } else {
52074  DUK_DDD(DUK_DDDPRINT("key is not a number"));
52075  return NULL;
52076  }
52077 
52078  /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
52079  * is 0xffffffffUL. We don't need to check for that explicitly
52080  * because 0xffffffffUL will never be inside object 'a_size'.
52081  */
52082 
52083  if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
52084  DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
52085  return NULL;
52086  }
52087  DUK_ASSERT(idx != 0xffffffffUL);
52088  DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
52089 
52090  /* XXX: for array instances we could take a shortcut here and assume
52091  * Array.prototype doesn't contain an array index property.
52092  */
52093 
52094  DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
52095  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
52096  if (!DUK_TVAL_IS_UNUSED(tv)) {
52097  DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
52098  return tv;
52099  }
52100 
52101  DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
52102  return NULL;
52103 }
52104 
52105 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) {
52106  duk_tval *tv;
52107  duk_harray *a;
52108  duk_uint32_t idx;
52109  duk_uint32_t old_len, new_len;
52110 
52111  if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
52112  DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
52113  DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
52114  return 0;
52115  }
52116  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures */
52117 
52118  a = (duk_harray *) obj;
52119  DUK_ASSERT_HARRAY_VALID(a);
52120 
52121 #if defined(DUK_USE_FASTINT)
52122  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52123  idx = duk__tval_fastint_to_arr_idx(tv_key);
52124  } else
52125 #endif
52126  if (DUK_TVAL_IS_DOUBLE(tv_key)) {
52127  idx = duk__tval_number_to_arr_idx(tv_key);
52128  } else {
52129  DUK_DDD(DUK_DDDPRINT("key is not a number"));
52130  return 0;
52131  }
52132 
52133  /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
52134  * is 0xffffffffUL. We don't need to check for that explicitly
52135  * because 0xffffffffUL will never be inside object 'a_size'.
52136  */
52137 
52138  if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) { /* for resizing of array part, use slow path */
52139  return 0;
52140  }
52141  DUK_ASSERT(idx != 0xffffffffUL);
52142  DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
52143 
52144  old_len = a->length;
52145 
52146  if (idx >= old_len) {
52147  DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
52148  "(arr_idx=%ld, old_len=%ld)",
52149  (long) idx, (long) old_len));
52150  if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
52151  /* The correct behavior here is either a silent error
52152  * or a TypeError, depending on strictness. Fall back
52153  * to the slow path to handle the situation.
52154  */
52155  return 0;
52156  }
52157  new_len = idx + 1;
52158 
52159  ((duk_harray *) obj)->length = new_len;
52160  }
52161 
52162  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
52163  DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects */
52164 
52165  DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
52166  return 1;
52167 }
52168 #endif /* DUK_USE_ARRAY_PROP_FASTPATH */
52169 
52170 /*
52171  * Fast path for bufobj getprop/putprop
52172  */
52173 
52174 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
52175 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
52176  duk_context *ctx;
52177  duk_uint32_t idx;
52178  duk_hbufobj *h_bufobj;
52179  duk_uint_t byte_off;
52180  duk_small_uint_t elem_size;
52181  duk_uint8_t *data;
52182 
52183  ctx = (duk_context *) thr;
52184 
52185  if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
52186  return 0;
52187  }
52188  h_bufobj = (duk_hbufobj *) obj;
52189  if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
52190  return 0;
52191  }
52192 
52193 #if defined(DUK_USE_FASTINT)
52194  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52195  idx = duk__tval_fastint_to_arr_idx(tv_key);
52196  } else
52197 #endif
52198  if (DUK_TVAL_IS_DOUBLE(tv_key)) {
52199  idx = duk__tval_number_to_arr_idx(tv_key);
52200  } else {
52201  return 0;
52202  }
52203 
52204  /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
52205  * is 0xffffffffUL. We don't need to check for that explicitly
52206  * because 0xffffffffUL will never be inside bufobj length.
52207  */
52208 
52209  /* Careful with wrapping (left shifting idx would be unsafe). */
52210  if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
52211  return 0;
52212  }
52213  DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
52214 
52215  byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
52216  elem_size = 1 << h_bufobj->shift;
52217 
52218  if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
52219  data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
52220  duk_hbufobj_push_validated_read(ctx, h_bufobj, data, elem_size);
52221  } else {
52222  DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
52223  duk_push_uint(ctx, 0);
52224  }
52225 
52226  return 1;
52227 }
52228 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
52229 
52230 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
52231 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
52232  duk_context *ctx;
52233  duk_uint32_t idx;
52234  duk_hbufobj *h_bufobj;
52235  duk_uint_t byte_off;
52236  duk_small_uint_t elem_size;
52237  duk_uint8_t *data;
52238 
52239  ctx = (duk_context *) thr;
52240 
52241  if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
52242  DUK_TVAL_IS_NUMBER(tv_val))) {
52243  return 0;
52244  }
52245  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)); /* caller ensures; rom objects are never bufobjs now */
52246 
52247  h_bufobj = (duk_hbufobj *) obj;
52248  if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
52249  return 0;
52250  }
52251 
52252 #if defined(DUK_USE_FASTINT)
52253  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52254  idx = duk__tval_fastint_to_arr_idx(tv_key);
52255  } else
52256 #endif
52257  if (DUK_TVAL_IS_DOUBLE(tv_key)) {
52258  idx = duk__tval_number_to_arr_idx(tv_key);
52259  } else {
52260  return 0;
52261  }
52262 
52263  /* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
52264  * is 0xffffffffUL. We don't need to check for that explicitly
52265  * because 0xffffffffUL will never be inside bufobj length.
52266  */
52267 
52268  /* Careful with wrapping (left shifting idx would be unsafe). */
52269  if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
52270  return 0;
52271  }
52272  DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
52273 
52274  byte_off = idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
52275  elem_size = 1 << h_bufobj->shift;
52276 
52277  /* Value is required to be a number in the fast path so there
52278  * are no side effects in write coercion.
52279  */
52280  duk_push_tval(ctx, tv_val);
52281  DUK_ASSERT(duk_is_number(ctx, -1));
52282 
52283  if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
52284  data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
52285  duk_hbufobj_validated_write(ctx, h_bufobj, data, elem_size);
52286  } else {
52287  DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
52288  }
52289 
52290  duk_pop(ctx);
52291  return 1;
52292 }
52293 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
52294 
52295 /*
52296  * GETPROP: Ecmascript property read.
52297  */
52298 
52299 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
52300  duk_context *ctx = (duk_context *) thr;
52301  duk_tval tv_obj_copy;
52302  duk_tval tv_key_copy;
52303  duk_hobject *curr = NULL;
52304  duk_hstring *key = NULL;
52305  duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
52306  duk_propdesc desc;
52307  duk_uint_t sanity;
52308 
52309  DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
52310  (void *) thr, (void *) tv_obj, (void *) tv_key,
52311  (duk_tval *) tv_obj, (duk_tval *) tv_key));
52312 
52313  DUK_ASSERT(ctx != NULL);
52314  DUK_ASSERT(thr != NULL);
52315  DUK_ASSERT(thr->heap != NULL);
52316  DUK_ASSERT(tv_obj != NULL);
52317  DUK_ASSERT(tv_key != NULL);
52318 
52319  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52320 
52321  /*
52322  * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
52323  * them being invalidated by a valstack resize.
52324  *
52325  * XXX: this is now an overkill for many fast paths. Rework this
52326  * to be faster (although switching to a valstack discipline might
52327  * be a better solution overall).
52328  */
52329 
52330  DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
52331  DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
52332  tv_obj = &tv_obj_copy;
52333  tv_key = &tv_key_copy;
52334 
52335  /*
52336  * Coercion and fast path processing
52337  */
52338 
52339  switch (DUK_TVAL_GET_TAG(tv_obj)) {
52340  case DUK_TAG_UNDEFINED:
52341  case DUK_TAG_NULL: {
52342  /* Note: unconditional throw */
52343  DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
52344 #if defined(DUK_USE_PARANOID_ERRORS)
52345  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
52346 #else
52347  DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
52348  duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
52349 #endif
52350  return 0;
52351  }
52352 
52353  case DUK_TAG_BOOLEAN: {
52354  DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
52355  curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
52356  break;
52357  }
52358 
52359  case DUK_TAG_STRING: {
52360  duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
52361  duk_int_t pop_count;
52362 
52363  if (DUK_HSTRING_HAS_SYMBOL(h)) {
52364  /* Symbols (ES2015 or hidden) don't have virtual properties. */
52365  DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
52366  curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
52367  break;
52368  }
52369 
52370 #if defined(DUK_USE_FASTINT)
52371  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52372  arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
52373  DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
52374  pop_count = 0;
52375  } else
52376 #endif
52377  if (DUK_TVAL_IS_NUMBER(tv_key)) {
52378  arr_idx = duk__tval_number_to_arr_idx(tv_key);
52379  DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
52380  pop_count = 0;
52381  } else {
52382  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52383  DUK_ASSERT(key != NULL);
52384  DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
52385  "coercion key is %!T, arr_idx %ld",
52386  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
52387  pop_count = 1;
52388  }
52389 
52390  if (arr_idx != DUK__NO_ARRAY_INDEX &&
52391  arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
52392  duk_pop_n(ctx, pop_count);
52393  duk_push_hstring(ctx, h);
52394  duk_substring(ctx, -1, arr_idx, arr_idx + 1); /* [str] -> [substr] */
52395 
52396  DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
52397  "after coercion -> return char)",
52398  (duk_tval *) duk_get_tval(ctx, -1)));
52399  return 1;
52400  }
52401 
52402  if (pop_count == 0) {
52403  /* This is a pretty awkward control flow, but we need to recheck the
52404  * key coercion here.
52405  */
52406  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52407  DUK_ASSERT(key != NULL);
52408  DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
52409  "coercion key is %!T, arr_idx %ld",
52410  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
52411  }
52412 
52413  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52414  duk_pop(ctx); /* [key] -> [] */
52415  duk_push_uint(ctx, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h)); /* [] -> [res] */
52416 
52417  DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
52418  "return string length)",
52419  (duk_tval *) duk_get_tval(ctx, -1)));
52420  return 1;
52421  }
52422 
52423  DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
52424  curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
52425  goto lookup; /* avoid double coercion */
52426  }
52427 
52428  case DUK_TAG_OBJECT: {
52429 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
52430  duk_tval *tmp;
52431 #endif
52432 
52433  curr = DUK_TVAL_GET_OBJECT(tv_obj);
52434  DUK_ASSERT(curr != NULL);
52435 
52436  /* XXX: array .length fast path (important in e.g. loops)? */
52437 
52438 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
52439  tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
52440  if (tmp) {
52441  duk_push_tval(ctx, tmp);
52442 
52443  DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
52444  "fast path)",
52445  (duk_tval *) duk_get_tval(ctx, -1)));
52446  return 1;
52447  }
52448 #endif
52449 
52450 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
52451  if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
52452  /* Read value pushed on stack. */
52453  DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
52454  "fast path)",
52455  (duk_tval *) duk_get_tval(ctx, -1)));
52456  return 1;
52457  }
52458 #endif
52459 
52460 #if defined(DUK_USE_ES6_PROXY)
52461  if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(curr))) {
52462  duk_hobject *h_target;
52463 
52464  if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
52465  /* -> [ ... trap handler ] */
52466  DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
52467  duk_push_hobject(ctx, h_target); /* target */
52468  duk_push_tval(ctx, tv_key); /* P */
52469  duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
52470  duk_call_method(ctx, 3 /*nargs*/);
52471 
52472  /* Target object must be checked for a conflicting
52473  * non-configurable property.
52474  */
52475  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52476  DUK_ASSERT(key != NULL);
52477 
52478  if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
52479  duk_tval *tv_hook = duk_require_tval(ctx, -3); /* value from hook */
52480  duk_tval *tv_targ = duk_require_tval(ctx, -1); /* value from target */
52481  duk_bool_t datadesc_reject;
52482  duk_bool_t accdesc_reject;
52483 
52484  DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
52485  "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
52486  "desc.get=%p, desc.set=%p",
52487  (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
52488  (unsigned long) desc.flags,
52489  (void *) desc.get, (void *) desc.set));
52490 
52491  datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
52492  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
52493  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
52494  !duk_js_samevalue(tv_hook, tv_targ);
52495  accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
52496  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
52497  (desc.get == NULL) &&
52498  !DUK_TVAL_IS_UNDEFINED(tv_hook);
52499  if (datadesc_reject || accdesc_reject) {
52500  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
52501  }
52502 
52503  duk_pop_2(ctx);
52504  } else {
52505  duk_pop(ctx);
52506  }
52507  return 1; /* return value */
52508  }
52509 
52510  curr = h_target; /* resume lookup from target */
52511  DUK_TVAL_SET_OBJECT(tv_obj, curr);
52512  }
52513 #endif /* DUK_USE_ES6_PROXY */
52514 
52515  if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
52516  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52517  DUK_ASSERT(key != NULL);
52518 
52519  if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
52520  DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
52521  "key matches magically bound property -> skip standard "
52522  "Get with replacement value)",
52523  (duk_tval *) duk_get_tval(ctx, -1)));
52524 
52525  /* no need for 'caller' post-check, because 'key' must be an array index */
52526 
52527  duk_remove_m2(ctx); /* [key result] -> [result] */
52528  return 1;
52529  }
52530 
52531  goto lookup; /* avoid double coercion */
52532  }
52533  break;
52534  }
52535 
52536  /* Buffer has virtual properties similar to string, but indexed values
52537  * are numbers, not 1-byte buffers/strings which would perform badly.
52538  */
52539  case DUK_TAG_BUFFER: {
52540  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
52541  duk_int_t pop_count;
52542 
52543  /*
52544  * Because buffer values are often looped over, a number fast path
52545  * is important.
52546  */
52547 
52548 #if defined(DUK_USE_FASTINT)
52549  if (DUK_TVAL_IS_FASTINT(tv_key)) {
52550  arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
52551  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
52552  pop_count = 0;
52553  }
52554  else
52555 #endif
52556  if (DUK_TVAL_IS_NUMBER(tv_key)) {
52557  arr_idx = duk__tval_number_to_arr_idx(tv_key);
52558  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
52559  pop_count = 0;
52560  } else {
52561  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52562  DUK_ASSERT(key != NULL);
52563  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
52564  "coercion key is %!T, arr_idx %ld",
52565  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
52566  pop_count = 1;
52567  }
52568 
52569  if (arr_idx != DUK__NO_ARRAY_INDEX &&
52570  arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
52571  duk_pop_n(ctx, pop_count);
52572  duk_push_uint(ctx, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
52573 
52574  DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
52575  "after coercion -> return byte as number)",
52576  (duk_tval *) duk_get_tval(ctx, -1)));
52577  return 1;
52578  }
52579 
52580  if (pop_count == 0) {
52581  /* This is a pretty awkward control flow, but we need to recheck the
52582  * key coercion here.
52583  */
52584  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52585  DUK_ASSERT(key != NULL);
52586  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
52587  "coercion key is %!T, arr_idx %ld",
52588  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
52589  }
52590 
52591  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52592  duk_pop(ctx); /* [key] -> [] */
52593  duk_push_uint(ctx, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h)); /* [] -> [res] */
52594 
52595  DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
52596  "after coercion -> return buffer length)",
52597  (duk_tval *) duk_get_tval(ctx, -1)));
52598  return 1;
52599  }
52600 
52601  DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
52602  curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
52603  goto lookup; /* avoid double coercion */
52604  }
52605 
52606  case DUK_TAG_POINTER: {
52607  DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
52608  curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
52609  break;
52610  }
52611 
52612  case DUK_TAG_LIGHTFUNC: {
52613  duk_int_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_obj);
52614 
52615  /* Must coerce key: if key is an object, it may coerce to e.g. 'length'. */
52616  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52617 
52618  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
52619  duk_int_t lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
52620  duk_pop(ctx);
52621  duk_push_int(ctx, lf_len);
52622  return 1;
52623  } else if (key == DUK_HTHREAD_STRING_NAME(thr)) {
52624  duk_pop(ctx);
52625  duk_push_lightfunc_name(ctx, tv_obj);
52626  return 1;
52627  }
52628 
52629  DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
52630  curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
52631  goto lookup; /* avoid double coercion */
52632  }
52633 
52634 #if defined(DUK_USE_FASTINT)
52635  case DUK_TAG_FASTINT:
52636 #endif
52637  default: {
52638  /* number */
52639  DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
52640  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
52641  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
52642  curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
52643  break;
52644  }
52645  }
52646 
52647  /* key coercion (unless already coerced above) */
52648  DUK_ASSERT(key == NULL);
52649  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52650  DUK_ASSERT(key != NULL);
52651 
52652  /*
52653  * Property lookup
52654  */
52655 
52656  lookup:
52657  /* [key] (coerced) */
52658  DUK_ASSERT(curr != NULL);
52659  DUK_ASSERT(key != NULL);
52660 
52661  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
52662  do {
52663  if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
52664  goto next_in_chain;
52665  }
52666 
52667  if (desc.get != NULL) {
52668  /* accessor with defined getter */
52669  DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
52670 
52671  duk_pop(ctx); /* [key undefined] -> [key] */
52672  duk_push_hobject(ctx, desc.get);
52673  duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
52674 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
52675  duk_dup_m3(ctx);
52676  duk_call_method(ctx, 1); /* [key getter this key] -> [key retval] */
52677 #else
52678  duk_call_method(ctx, 0); /* [key getter this] -> [key retval] */
52679 #endif
52680  } else {
52681  /* [key value] or [key undefined] */
52682 
52683  /* data property or accessor without getter */
52684  DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
52685  (desc.get == NULL));
52686 
52687  /* if accessor without getter, return value is undefined */
52688  DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
52689  duk_is_undefined(ctx, -1));
52690 
52691  /* Note: for an accessor without getter, falling through to
52692  * check for "caller" exotic behavior is unnecessary as
52693  * "undefined" will never activate the behavior. But it does
52694  * no harm, so we'll do it anyway.
52695  */
52696  }
52697 
52698  goto found; /* [key result] */
52699 
52700  next_in_chain:
52701  /* XXX: option to pretend property doesn't exist if sanity limit is
52702  * hit might be useful.
52703  */
52704  if (sanity-- == 0) {
52705  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
52706  }
52707  curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
52708  } while (curr);
52709 
52710  /*
52711  * Not found
52712  */
52713 
52714  duk_to_undefined(ctx, -1); /* [key] -> [undefined] (default value) */
52715 
52716  DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(ctx, -1)));
52717  return 0;
52718 
52719  /*
52720  * Found; post-processing (Function and arguments objects)
52721  */
52722 
52723  found:
52724  /* [key result] */
52725 
52726 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
52727  /* Special behavior for 'caller' property of (non-bound) function objects
52728  * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
52729  * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
52730  * Quite interestingly, a non-strict function with no formal arguments
52731  * will get an arguments object -without- special 'caller' behavior!
52732  *
52733  * The E5.1 spec is a bit ambiguous if this special behavior applies when
52734  * a bound function is the base value (not the 'caller' value): Section
52735  * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
52736  * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
52737  * However, Section 13.3.5.4 has "NOTE: Function objects created using
52738  * Function.prototype.bind use the default [[Get]] internal method."
52739  * The current implementation assumes this means that bound functions
52740  * should not have the special [[Get]] behavior.
52741  *
52742  * The E5.1 spec is also a bit unclear if the TypeError throwing is
52743  * applied if the 'caller' value is a strict bound function. The
52744  * current implementation will throw even for both strict non-bound
52745  * and strict bound functions.
52746  *
52747  * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
52748  * tests.
52749  *
52750  * This exotic behavior is disabled when the non-standard 'caller' property
52751  * is enabled, as it conflicts with the free use of 'caller'.
52752  */
52753  if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
52754  DUK_TVAL_IS_OBJECT(tv_obj)) {
52755  duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
52756  DUK_ASSERT(orig != NULL);
52757 
52758  if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
52759  DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
52760  duk_hobject *h;
52761 
52762  /* XXX: The TypeError is currently not applied to bound
52763  * functions because the 'strict' flag is not copied by
52764  * bind(). This may or may not be correct, the specification
52765  * only refers to the value being a "strict mode Function
52766  * object" which is ambiguous.
52767  */
52768  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
52769 
52770  h = duk_get_hobject(ctx, -1); /* NULL if not an object */
52771  if (h &&
52772  DUK_HOBJECT_IS_FUNCTION(h) &&
52773  DUK_HOBJECT_HAS_STRICT(h)) {
52774  /* XXX: sufficient to check 'strict', assert for 'is function' */
52775  DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
52776  }
52777  }
52778  }
52779 #endif /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
52780 
52781  duk_remove_m2(ctx); /* [key result] -> [result] */
52782 
52783  DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(ctx, -1)));
52784  return 1;
52785 }
52786 
52787 /*
52788  * HASPROP: Ecmascript property existence check ("in" operator).
52789  *
52790  * Interestingly, the 'in' operator does not do any coercion of
52791  * the target object.
52792  */
52793 
52794 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
52795  duk_context *ctx = (duk_context *) thr;
52796  duk_tval tv_key_copy;
52797  duk_hobject *obj;
52798  duk_hstring *key;
52799  duk_uint32_t arr_idx;
52800  duk_bool_t rc;
52801  duk_propdesc desc;
52802 
52803  DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
52804  (void *) thr, (void *) tv_obj, (void *) tv_key,
52805  (duk_tval *) tv_obj, (duk_tval *) tv_key));
52806 
52807  DUK_ASSERT(thr != NULL);
52808  DUK_ASSERT(thr->heap != NULL);
52809  DUK_ASSERT(tv_obj != NULL);
52810  DUK_ASSERT(tv_key != NULL);
52811  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52812 
52813  DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
52814  tv_key = &tv_key_copy;
52815 
52816  /*
52817  * The 'in' operator requires an object as its right hand side,
52818  * throwing a TypeError unconditionally if this is not the case.
52819  *
52820  * However, lightfuncs need to behave like fully fledged objects
52821  * here to be maximally transparent, so we need to handle them
52822  * here. Same goes for plain buffers which behave like ArrayBuffers.
52823  */
52824 
52825  /* XXX: Refactor key coercion so that it's only called once. It can't
52826  * be trivially lifted here because the object must be type checked
52827  * first.
52828  */
52829 
52830  if (DUK_TVAL_IS_OBJECT(tv_obj)) {
52831  obj = DUK_TVAL_GET_OBJECT(tv_obj);
52832  DUK_ASSERT(obj != NULL);
52833 
52834  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52835  } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
52836  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52837  if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
52838  rc = 1;
52839  goto pop_and_return;
52840  }
52841  obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
52842  } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
52843  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
52844  if (duk__key_is_lightfunc_ownprop(thr, key)) {
52845  rc = 1;
52846  goto pop_and_return;
52847  }
52848 
52849  /* If not found, resume existence check from Function.prototype.
52850  * We can just substitute the value in this case; nothing will
52851  * need the original base value (as would be the case with e.g.
52852  * setters/getters.
52853  */
52854  obj = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
52855  } else {
52856  /* Note: unconditional throw */
52857  DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
52858  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
52859  }
52860 
52861  /* XXX: fast path for arrays? */
52862 
52863  DUK_ASSERT(key != NULL);
52864  DUK_ASSERT(obj != NULL);
52865  DUK_UNREF(arr_idx);
52866 
52867 #if defined(DUK_USE_ES6_PROXY)
52868  if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
52869  duk_hobject *h_target;
52870  duk_bool_t tmp_bool;
52871 
52872  /* XXX: the key in 'key in obj' is string coerced before we're called
52873  * (which is the required behavior in E5/E5.1/E6) so the key is a string
52874  * here already.
52875  */
52876 
52877  if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
52878  /* [ ... key trap handler ] */
52879  DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
52880  duk_push_hobject(ctx, h_target); /* target */
52881  duk_push_tval(ctx, tv_key); /* P */
52882  duk_call_method(ctx, 2 /*nargs*/);
52883  tmp_bool = duk_to_boolean(ctx, -1);
52884  if (!tmp_bool) {
52885  /* Target object must be checked for a conflicting
52886  * non-configurable property.
52887  */
52888 
52889  if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
52890  DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
52891  "conflicting property; desc.flags=0x%08lx, "
52892  "desc.get=%p, desc.set=%p",
52893  (duk_heaphdr *) key, (unsigned long) desc.flags,
52894  (void *) desc.get, (void *) desc.set));
52895  /* XXX: Extensibility check for target uses IsExtensible(). If we
52896  * implemented the isExtensible trap and didn't reject proxies as
52897  * proxy targets, it should be respected here.
52898  */
52899  if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && /* property is configurable and */
52900  DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) { /* ... target is extensible */
52901  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
52902  }
52903  }
52904  }
52905 
52906  duk_pop_2(ctx); /* [ key trap_result ] -> [] */
52907  return tmp_bool;
52908  }
52909 
52910  obj = h_target; /* resume check from proxy target */
52911  }
52912 #endif /* DUK_USE_ES6_PROXY */
52913 
52914  /* XXX: inline into a prototype walking loop? */
52915 
52916  rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/); /* don't push value */
52917  /* fall through */
52918 
52919  pop_and_return:
52920  duk_pop(ctx); /* [ key ] -> [] */
52921  return rc;
52922 }
52923 
52924 /*
52925  * HASPROP variant used internally.
52926  *
52927  * This primitive must never throw an error, callers rely on this.
52928  * In particular, don't throw an error for prototype loops; instead,
52929  * pretend like the property doesn't exist if a prototype sanity limit
52930  * is reached.
52931  *
52932  * Does not implement proxy behavior: if applied to a proxy object,
52933  * returns key existence on the proxy object itself.
52934  */
52935 
52936 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
52937  duk_propdesc dummy;
52938 
52939  DUK_ASSERT(thr != NULL);
52940  DUK_ASSERT(thr->heap != NULL);
52941  DUK_ASSERT(obj != NULL);
52942  DUK_ASSERT(key != NULL);
52943 
52944  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
52945 
52946  return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP); /* don't push value */
52947 }
52948 
52949 /*
52950  * Helper: handle Array object 'length' write which automatically
52951  * deletes properties, see E5 Section 15.4.5.1, step 3. This is
52952  * quite tricky to get right.
52953  *
52954  * Used by duk_hobject_putprop().
52955  */
52956 
52957 /* Coerce a new .length candidate to a number and check that it's a valid
52958  * .length.
52959  */
52960 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
52961  duk_uint32_t res;
52962  duk_double_t d;
52963 
52964 #if !defined(DUK_USE_PREFER_SIZE)
52965 #if defined(DUK_USE_FASTINT)
52966  /* When fastints are enabled, the most interesting case is assigning
52967  * a fastint to .length (e.g. arr.length = 0).
52968  */
52969  if (DUK_TVAL_IS_FASTINT(tv)) {
52970  /* Very common case. */
52971  duk_int64_t fi;
52972  fi = DUK_TVAL_GET_FASTINT(tv);
52973  if (fi < 0 || fi > 0xffffffffLL) {
52974  goto fail_range;
52975  }
52976  return (duk_uint32_t) fi;
52977  }
52978 #else /* DUK_USE_FASTINT */
52979  /* When fastints are not enabled, the most interesting case is any
52980  * number.
52981  */
52982  if (DUK_TVAL_IS_DOUBLE(tv)) {
52983  d = DUK_TVAL_GET_NUMBER(tv);
52984  }
52985 #endif /* DUK_USE_FASTINT */
52986  else
52987 #endif /* !DUK_USE_PREFER_SIZE */
52988  {
52989  /* In all other cases, and when doing a size optimized build,
52990  * fall back to the comprehensive handler.
52991  */
52992  d = duk_js_tonumber(thr, tv);
52993  }
52994 
52995  /* Refuse to update an Array's 'length' to a value outside the
52996  * 32-bit range. Negative zero is accepted as zero.
52997  */
52998  res = (duk_uint32_t) d;
52999  if ((duk_double_t) res != d) {
53000  goto fail_range;
53001  }
53002 
53003  return res;
53004 
53005  fail_range:
53006  DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
53007  return 0; /* unreachable */
53008 }
53009 
53010 /* Delete elements required by a smaller length, taking into account
53011  * potentially non-configurable elements. Returns non-zero if all
53012  * elements could be deleted, and zero if all or some elements could
53013  * not be deleted. Also writes final "target length" to 'out_result_len'.
53014  * This is the length value that should go into the 'length' property
53015  * (must be set by the caller). Never throws an error.
53016  */
53017 DUK_LOCAL
53018 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
53019  duk_hobject *obj,
53020  duk_uint32_t old_len,
53021  duk_uint32_t new_len,
53022  duk_bool_t force_flag,
53023  duk_uint32_t *out_result_len) {
53024  duk_uint32_t target_len;
53025  duk_uint_fast32_t i;
53026  duk_uint32_t arr_idx;
53027  duk_hstring *key;
53028  duk_tval *tv;
53029  duk_bool_t rc;
53030 
53031  DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
53032  "probably need to remove elements",
53033  (long) old_len, (long) new_len));
53034 
53035  /*
53036  * New length is smaller than old length, need to delete properties above
53037  * the new length.
53038  *
53039  * If array part exists, this is straightforward: array entries cannot
53040  * be non-configurable so this is guaranteed to work.
53041  *
53042  * If array part does not exist, array-indexed values are scattered
53043  * in the entry part, and some may not be configurable (preventing length
53044  * from becoming lower than their index + 1). To handle the algorithm
53045  * in E5 Section 15.4.5.1, step l correctly, we scan the entire property
53046  * set twice.
53047  */
53048 
53049  DUK_ASSERT(thr != NULL);
53050  DUK_ASSERT(obj != NULL);
53051  DUK_ASSERT(new_len < old_len);
53052  DUK_ASSERT(out_result_len != NULL);
53053  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
53054 
53055  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
53056  DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
53057 
53058  if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
53059  /*
53060  * All defined array-indexed properties are in the array part
53061  * (we assume the array part is comprehensive), and all array
53062  * entries are writable, configurable, and enumerable. Thus,
53063  * nothing can prevent array entries from being deleted.
53064  */
53065 
53066  DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
53067 
53068  if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
53069  /* XXX: assertion that entries >= old_len are already unused */
53070  i = old_len;
53071  } else {
53072  i = DUK_HOBJECT_GET_ASIZE(obj);
53073  }
53074  DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
53075 
53076  while (i > new_len) {
53077  i--;
53078  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
53079  DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
53080  }
53081 
53082  *out_result_len = new_len;
53083  return 1;
53084  } else {
53085  /*
53086  * Entries part is a bit more complex
53087  */
53088 
53089  /* Stage 1: find highest preventing non-configurable entry (if any).
53090  * When forcing, ignore non-configurability.
53091  */
53092 
53093  DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
53094 
53095  DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
53096  "(highest preventing non-configurable entry (if any))"));
53097 
53098  target_len = new_len;
53099  if (force_flag) {
53100  DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
53101  goto skip_stage1;
53102  }
53103  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53104  key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
53105  if (!key) {
53106  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
53107  continue;
53108  }
53109  if (!DUK_HSTRING_HAS_ARRIDX(key)) {
53110  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
53111  continue;
53112  }
53113 
53114  DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
53115  arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
53116  DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
53117  DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
53118 
53119  if (arr_idx < new_len) {
53120  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
53121  (long) i, (long) arr_idx));
53122  continue;
53123  }
53124  if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
53125  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
53126  (long) i, (long) arr_idx));
53127  continue;
53128  }
53129 
53130  /* relevant array index is non-configurable, blocks write */
53131  if (arr_idx >= target_len) {
53132  DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
53133  "update target_len %ld -> %ld",
53134  (long) i, (long) arr_idx, (long) target_len,
53135  (long) (arr_idx + 1)));
53136  target_len = arr_idx + 1;
53137  }
53138  }
53139  skip_stage1:
53140 
53141  /* stage 2: delete configurable entries above target length */
53142 
53143  DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
53144  (long) old_len, (long) new_len, (long) target_len));
53145 
53146  DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
53147  "entries >= target_len"));
53148 
53149  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
53150  key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
53151  if (!key) {
53152  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
53153  continue;
53154  }
53155  if (!DUK_HSTRING_HAS_ARRIDX(key)) {
53156  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
53157  continue;
53158  }
53159 
53160  DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key)); /* XXX: macro checks for array index flag, which is unnecessary here */
53161  arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
53162  DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
53163  DUK_ASSERT(arr_idx < old_len); /* consistency requires this */
53164 
53165  if (arr_idx < target_len) {
53166  DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
53167  (long) i, (long) arr_idx));
53168  continue;
53169  }
53170  DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)); /* stage 1 guarantees */
53171 
53172  DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
53173  (long) i, (long) arr_idx));
53174 
53175  /*
53176  * Slow delete, but we don't care as we're already in a very slow path.
53177  * The delete always succeeds: key has no exotic behavior, property
53178  * is configurable, and no resize occurs.
53179  */
53180  rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
53181  DUK_UNREF(rc);
53182  DUK_ASSERT(rc != 0);
53183  }
53184 
53185  /* stage 3: update length (done by caller), decide return code */
53186 
53187  DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
53188 
53189  *out_result_len = target_len;
53190 
53191  if (target_len == new_len) {
53192  DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
53193  return 1;
53194  }
53195  DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
53196  "full length adjustment), return error"));
53197  return 0;
53198  }
53199 
53200  DUK_UNREACHABLE();
53201 }
53202 
53203 /* XXX: is valstack top best place for argument? */
53204 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
53205  duk_context *ctx = (duk_context *) thr;
53206  duk_harray *a;
53207  duk_uint32_t old_len;
53208  duk_uint32_t new_len;
53209  duk_uint32_t result_len;
53210  duk_bool_t rc;
53211 
53212  DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
53213  "new val: %!T",
53214  (duk_tval *) duk_get_tval(ctx, -1)));
53215 
53216  DUK_ASSERT(thr != NULL);
53217  DUK_ASSERT(ctx != NULL);
53218  DUK_ASSERT(obj != NULL);
53219 
53220  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
53221 
53222  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
53223  DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
53224  a = (duk_harray *) obj;
53225  DUK_ASSERT_HARRAY_VALID(a);
53226 
53227  DUK_ASSERT(duk_is_valid_index(ctx, -1));
53228 
53229  /*
53230  * Get old and new length
53231  */
53232 
53233  old_len = a->length;
53234  new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(ctx, -1));
53235  DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
53236 
53237  /*
53238  * Writability check
53239  */
53240 
53241  if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
53242  DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
53243  return 0;
53244  }
53245 
53246  /*
53247  * New length not lower than old length => no changes needed
53248  * (not even array allocation).
53249  */
53250 
53251  if (new_len >= old_len) {
53252  DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
53253  a->length = new_len;
53254  return 1;
53255  }
53256 
53257  DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
53258 
53259  /*
53260  * New length lower than old length => delete elements, then
53261  * update length.
53262  *
53263  * Note: even though a bunch of elements have been deleted, the 'desc' is
53264  * still valid as properties haven't been resized (and entries compacted).
53265  */
53266 
53267  rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
53268  DUK_ASSERT(result_len >= new_len && result_len <= old_len);
53269 
53270  a->length = result_len;
53271 
53272  /* XXX: shrink array allocation or entries compaction here? */
53273 
53274  return rc;
53275 }
53276 
53277 /*
53278  * PUTPROP: Ecmascript property write.
53279  *
53280  * Unlike Ecmascript primitive which returns nothing, returns 1 to indicate
53281  * success and 0 to indicate failure (assuming throw is not set).
53282  *
53283  * This is an extremely tricky function. Some examples:
53284  *
53285  * * Currently a decref may trigger a GC, which may compact an object's
53286  * property allocation. Consequently, any entry indices (e_idx) will
53287  * be potentially invalidated by a decref.
53288  *
53289  * * Exotic behaviors (strings, arrays, arguments object) require,
53290  * among other things:
53291  *
53292  * - Preprocessing before and postprocessing after an actual property
53293  * write. For example, array index write requires pre-checking the
53294  * array 'length' property for access control, and may require an
53295  * array 'length' update after the actual write has succeeded (but
53296  * not if it fails).
53297  *
53298  * - Deletion of multiple entries, as a result of array 'length' write.
53299  *
53300  * * Input values are taken as pointers which may point to the valstack.
53301  * If valstack is resized because of the put (this may happen at least
53302  * when the array part is abandoned), the pointers can be invalidated.
53303  * (We currently make a copy of all of the input values to avoid issues.)
53304  */
53305 
53306 DUK_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) {
53307  duk_context *ctx = (duk_context *) thr;
53308  duk_tval tv_obj_copy;
53309  duk_tval tv_key_copy;
53310  duk_tval tv_val_copy;
53311  duk_hobject *orig = NULL; /* NULL if tv_obj is primitive */
53312  duk_hobject *curr;
53313  duk_hstring *key = NULL;
53314  duk_propdesc desc;
53315  duk_tval *tv;
53316  duk_uint32_t arr_idx;
53317  duk_bool_t rc;
53318  duk_int_t e_idx;
53319  duk_uint_t sanity;
53320  duk_uint32_t new_array_length = 0; /* 0 = no update */
53321 
53322  DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
53323  "(obj -> %!T, key -> %!T, val -> %!T)",
53324  (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
53325  (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
53326 
53327  DUK_ASSERT(thr != NULL);
53328  DUK_ASSERT(thr->heap != NULL);
53329  DUK_ASSERT(ctx != NULL);
53330  DUK_ASSERT(tv_obj != NULL);
53331  DUK_ASSERT(tv_key != NULL);
53332  DUK_ASSERT(tv_val != NULL);
53333 
53334  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
53335 
53336  /*
53337  * Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
53338  * them being invalidated by a valstack resize.
53339  *
53340  * XXX: this is an overkill for some paths, so optimize this later
53341  * (or maybe switch to a stack arguments model entirely).
53342  */
53343 
53344  DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
53345  DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
53346  DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
53347  tv_obj = &tv_obj_copy;
53348  tv_key = &tv_key_copy;
53349  tv_val = &tv_val_copy;
53350 
53351  /*
53352  * Coercion and fast path processing.
53353  */
53354 
53355  switch (DUK_TVAL_GET_TAG(tv_obj)) {
53356  case DUK_TAG_UNDEFINED:
53357  case DUK_TAG_NULL: {
53358  /* Note: unconditional throw */
53359  DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
53360  (duk_tval *) tv_obj));
53361 #if defined(DUK_USE_PARANOID_ERRORS)
53362  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
53363 #else
53364  DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
53365  duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
53366 #endif
53367  return 0;
53368  }
53369 
53370  case DUK_TAG_BOOLEAN: {
53371  DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
53372  curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
53373  break;
53374  }
53375 
53376  case DUK_TAG_STRING: {
53377  duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
53378 
53379  /*
53380  * Note: currently no fast path for array index writes.
53381  * They won't be possible anyway as strings are immutable.
53382  */
53383 
53384  DUK_ASSERT(key == NULL);
53385  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53386  DUK_ASSERT(key != NULL);
53387 
53388  if (DUK_HSTRING_HAS_SYMBOL(h)) {
53389  /* Symbols (ES2015 or hidden) don't have virtual properties. */
53390  curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
53391  goto lookup;
53392  }
53393 
53394  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
53395  goto fail_not_writable;
53396  }
53397 
53398  if (arr_idx != DUK__NO_ARRAY_INDEX &&
53399  arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
53400  goto fail_not_writable;
53401  }
53402 
53403  DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
53404  curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
53405  goto lookup; /* avoid double coercion */
53406  }
53407 
53408  case DUK_TAG_OBJECT: {
53409  orig = DUK_TVAL_GET_OBJECT(tv_obj);
53410  DUK_ASSERT(orig != NULL);
53411 
53412 #if defined(DUK_USE_ROM_OBJECTS)
53413  /* With this check in place fast paths won't need read-only
53414  * object checks. This is technically incorrect if there are
53415  * setters that cause no writes to ROM objects, but current
53416  * built-ins don't have such setters.
53417  */
53418  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
53419  DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
53420  goto fail_not_writable_no_pop; /* Must avoid duk_pop() in exit path */
53421  }
53422 #endif
53423 
53424  /* The fast path for array property put is not fully compliant:
53425  * If one places conflicting number-indexed properties into
53426  * Array.prototype (for example, a non-writable Array.prototype[7])
53427  * the fast path will incorrectly ignore them.
53428  *
53429  * This fast path could be made compliant by falling through
53430  * to the slow path if the previous value was UNUSED. This would
53431  * also remove the need to check for extensibility. Right now a
53432  * non-extensible array is slower than an extensible one as far
53433  * as writes are concerned.
53434  *
53435  * The fast path behavior is documented in more detail here:
53436  * tests/ecmascript/test-misc-array-fast-write.js
53437  */
53438 
53439  /* XXX: array .length? */
53440 
53441 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
53442  if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
53443  DUK_DDD(DUK_DDDPRINT("array fast path success"));
53444  return 1;
53445  }
53446 #endif
53447 
53448 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53449  if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
53450  DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
53451  return 1;
53452  }
53453 #endif
53454 
53455 #if defined(DUK_USE_ES6_PROXY)
53456  if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(orig))) {
53457  duk_hobject *h_target;
53458  duk_bool_t tmp_bool;
53459 
53460  if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
53461  /* -> [ ... trap handler ] */
53462  DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
53463  duk_push_hobject(ctx, h_target); /* target */
53464  duk_push_tval(ctx, tv_key); /* P */
53465  duk_push_tval(ctx, tv_val); /* V */
53466  duk_push_tval(ctx, tv_obj); /* Receiver: Proxy object */
53467  duk_call_method(ctx, 4 /*nargs*/);
53468  tmp_bool = duk_to_boolean(ctx, -1);
53469  duk_pop(ctx);
53470  if (!tmp_bool) {
53471  goto fail_proxy_rejected;
53472  }
53473 
53474  /* Target object must be checked for a conflicting
53475  * non-configurable property.
53476  */
53477  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53478  DUK_ASSERT(key != NULL);
53479 
53480  if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
53481  duk_tval *tv_targ = duk_require_tval(ctx, -1);
53482  duk_bool_t datadesc_reject;
53483  duk_bool_t accdesc_reject;
53484 
53485  DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
53486  "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
53487  "desc.get=%p, desc.set=%p",
53488  (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
53489  (unsigned long) desc.flags,
53490  (void *) desc.get, (void *) desc.set));
53491 
53492  datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
53493  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
53494  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
53495  !duk_js_samevalue(tv_val, tv_targ);
53496  accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
53497  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
53498  (desc.set == NULL);
53499  if (datadesc_reject || accdesc_reject) {
53500  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
53501  }
53502 
53503  duk_pop_2(ctx);
53504  } else {
53505  duk_pop(ctx);
53506  }
53507  return 1; /* success */
53508  }
53509 
53510  orig = h_target; /* resume write to target */
53511  DUK_TVAL_SET_OBJECT(tv_obj, orig);
53512  }
53513 #endif /* DUK_USE_ES6_PROXY */
53514 
53515  curr = orig;
53516  break;
53517  }
53518 
53519  case DUK_TAG_BUFFER: {
53520  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
53521  duk_int_t pop_count = 0;
53522 
53523  /*
53524  * Because buffer values may be looped over and read/written
53525  * from, an array index fast path is important.
53526  */
53527 
53528 #if defined(DUK_USE_FASTINT)
53529  if (DUK_TVAL_IS_FASTINT(tv_key)) {
53530  arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
53531  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
53532  pop_count = 0;
53533  } else
53534 #endif
53535  if (DUK_TVAL_IS_NUMBER(tv_key)) {
53536  arr_idx = duk__tval_number_to_arr_idx(tv_key);
53537  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
53538  pop_count = 0;
53539  } else {
53540  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53541  DUK_ASSERT(key != NULL);
53542  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
53543  "coercion key is %!T, arr_idx %ld",
53544  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
53545  pop_count = 1;
53546  }
53547 
53548  if (arr_idx != DUK__NO_ARRAY_INDEX &&
53549  arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
53550  duk_uint8_t *data;
53551  DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
53552  data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
53553 
53554  /* XXX: duk_to_int() ensures we'll get 8 lowest bits as
53555  * as input is within duk_int_t range (capped outside it).
53556  */
53557 #if defined(DUK_USE_FASTINT)
53558  /* Buffer writes are often integers. */
53559  if (DUK_TVAL_IS_FASTINT(tv_val)) {
53560  data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
53561  }
53562  else
53563 #endif
53564  {
53565  duk_push_tval(ctx, tv_val);
53566  data[arr_idx] = (duk_uint8_t) duk_to_uint32(ctx, -1);
53567  pop_count++;
53568  }
53569 
53570  duk_pop_n(ctx, pop_count);
53571  DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
53572  return 1;
53573  }
53574 
53575  if (pop_count == 0) {
53576  /* This is a pretty awkward control flow, but we need to recheck the
53577  * key coercion here.
53578  */
53579  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53580  DUK_ASSERT(key != NULL);
53581  DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
53582  "coercion key is %!T, arr_idx %ld",
53583  (duk_tval *) duk_get_tval(ctx, -1), (long) arr_idx));
53584  }
53585 
53586  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
53587  goto fail_not_writable;
53588  }
53589 
53590  DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
53591  curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
53592  goto lookup; /* avoid double coercion */
53593  }
53594 
53595  case DUK_TAG_POINTER: {
53596  DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
53597  curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
53598  break;
53599  }
53600 
53601  case DUK_TAG_LIGHTFUNC: {
53602  /* All lightfunc own properties are non-writable and the lightfunc
53603  * is considered non-extensible. However, the write may be captured
53604  * by an inherited setter which means we can't stop the lookup here.
53605  */
53606 
53607  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53608 
53609  if (duk__key_is_lightfunc_ownprop(thr, key)) {
53610  goto fail_not_writable;
53611  }
53612 
53613  DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
53614  curr = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
53615  goto lookup; /* avoid double coercion */
53616  }
53617 
53618 #if defined(DUK_USE_FASTINT)
53619  case DUK_TAG_FASTINT:
53620 #endif
53621  default: {
53622  /* number */
53623  DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
53624  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
53625  curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
53626  break;
53627  }
53628  }
53629 
53630  DUK_ASSERT(key == NULL);
53631  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
53632  DUK_ASSERT(key != NULL);
53633 
53634  lookup:
53635 
53636  /*
53637  * Check whether the property already exists in the prototype chain.
53638  * Note that the actual write goes into the original base object
53639  * (except if an accessor property captures the write).
53640  */
53641 
53642  /* [key] */
53643 
53644  DUK_ASSERT(curr != NULL);
53645  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
53646  do {
53647  if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
53648  goto next_in_chain;
53649  }
53650 
53651  if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
53652  /*
53653  * Found existing accessor property (own or inherited).
53654  * Call setter with 'this' set to orig, and value as the only argument.
53655  * Setter calls are OK even for ROM objects.
53656  *
53657  * Note: no exotic arguments object behavior, because [[Put]] never
53658  * calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
53659  */
53660 
53661  duk_hobject *setter;
53662 
53663  DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
53664 
53665  setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
53666  if (!setter) {
53667  goto fail_no_setter;
53668  }
53669  duk_push_hobject(ctx, setter);
53670  duk_push_tval(ctx, tv_obj); /* note: original, uncoerced base */
53671  duk_push_tval(ctx, tv_val); /* [key setter this val] */
53672 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
53673  duk_dup_m4(ctx);
53674  duk_call_method(ctx, 2); /* [key setter this val key] -> [key retval] */
53675 #else
53676  duk_call_method(ctx, 1); /* [key setter this val] -> [key retval] */
53677 #endif
53678  duk_pop(ctx); /* ignore retval -> [key] */
53679  goto success_no_arguments_exotic;
53680  }
53681 
53682  if (orig == NULL) {
53683  /*
53684  * Found existing own or inherited plain property, but original
53685  * base is a primitive value.
53686  */
53687  DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
53688  goto fail_base_primitive;
53689  }
53690 
53691  if (curr != orig) {
53692  /*
53693  * Found existing inherited plain property.
53694  * Do an access control check, and if OK, write
53695  * new property to 'orig'.
53696  */
53697  if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
53698  DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
53699  goto fail_not_extensible;
53700  }
53701  if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
53702  DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
53703  goto fail_not_writable;
53704  }
53705  DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
53706  goto create_new;
53707  } else {
53708  /*
53709  * Found existing own (non-inherited) plain property.
53710  * Do an access control check and update in place.
53711  */
53712 
53713  if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
53714  DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
53715  goto fail_not_writable;
53716  }
53717  if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
53718  DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
53719 
53720  if (DUK_HOBJECT_IS_ARRAY(curr)) {
53721  /*
53722  * Write to 'length' of an array is a very complex case
53723  * handled in a helper which updates both the array elements
53724  * and writes the new 'length'. The write may result in an
53725  * unconditional RangeError or a partial write (indicated
53726  * by a return code).
53727  *
53728  * Note: the helper has an unnecessary writability check
53729  * for 'length', we already know it is writable.
53730  */
53731  DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr)); /* only virtual array property */
53732 
53733  DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
53734 
53735  /* XXX: the helper currently assumes stack top contains new
53736  * 'length' value and the whole calling convention is not very
53737  * compatible with what we need.
53738  */
53739 
53740  duk_push_tval(ctx, tv_val); /* [key val] */
53741  rc = duk__handle_put_array_length(thr, orig);
53742  duk_pop(ctx); /* [key val] -> [key] */
53743  if (!rc) {
53744  goto fail_array_length_partial;
53745  }
53746 
53747  /* key is 'length', cannot match argument exotic behavior */
53748  goto success_no_arguments_exotic;
53749  }
53750 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53751  else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
53752  duk_hbufobj *h_bufobj;
53753  duk_uint_t byte_off;
53754  duk_small_uint_t elem_size;
53755 
53756  h_bufobj = (duk_hbufobj *) curr;
53757  DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
53758 
53759  DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
53760 
53761  /* Careful with wrapping: arr_idx upshift may easily wrap, whereas
53762  * length downshift won't.
53763  */
53764  if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
53765  duk_uint8_t *data;
53766  DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
53767 
53768  DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX); /* index/length check guarantees */
53769  byte_off = arr_idx << h_bufobj->shift; /* no wrap assuming h_bufobj->length is valid */
53770  elem_size = 1 << h_bufobj->shift;
53771 
53772  /* Coerce to number before validating pointers etc so that the
53773  * number coercions in duk_hbufobj_validated_write() are
53774  * guaranteed to be side effect free and not invalidate the
53775  * pointer checks we do here.
53776  */
53777  duk_push_tval(ctx, tv_val);
53778  (void) duk_to_number_m1(ctx);
53779 
53780  if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
53781  data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
53782  duk_hbufobj_validated_write(ctx, h_bufobj, data, elem_size);
53783  } else {
53784  DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
53785  }
53786  duk_pop(ctx);
53787  goto success_no_arguments_exotic;
53788  }
53789  }
53790 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
53791 
53792  DUK_D(DUK_DPRINT("should not happen, key %!O", key));
53793  goto fail_internal; /* should not happen */
53794  }
53795  DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
53796  goto update_old;
53797  }
53798  DUK_UNREACHABLE();
53799 
53800  next_in_chain:
53801  /* XXX: option to pretend property doesn't exist if sanity limit is
53802  * hit might be useful.
53803  */
53804  if (sanity-- == 0) {
53805  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
53806  }
53807  curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
53808  } while (curr);
53809 
53810  /*
53811  * Property not found in prototype chain.
53812  */
53813 
53814  DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
53815 
53816  if (orig == NULL) {
53817  DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
53818  goto fail_base_primitive;
53819  }
53820 
53821  if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
53822  DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
53823  goto fail_not_extensible;
53824  }
53825 
53826  goto create_new;
53827 
53828  update_old:
53829 
53830  /*
53831  * Update an existing property of the base object.
53832  */
53833 
53834  /* [key] */
53835 
53836  DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
53837 
53838  DUK_ASSERT(orig != NULL);
53839 #if defined(DUK_USE_ROM_OBJECTS)
53840  /* This should not happen because DUK_TAG_OBJECT case checks
53841  * for this already, but check just in case.
53842  */
53843  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
53844  goto fail_not_writable;
53845  }
53846 #endif
53847 
53848  /* Although there are writable virtual properties (e.g. plain buffer
53849  * and buffer object number indices), they are handled before we come
53850  * here.
53851  */
53852  DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
53853  DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
53854 
53855  /* Array own property .length is handled above. */
53856  DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
53857 
53858  if (desc.e_idx >= 0) {
53859  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
53860  DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
53861  DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; e_idx may be invalidated */
53862  /* don't touch property attributes or hash part */
53863  DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
53864  (long) desc.e_idx, (duk_tval *) tv));
53865  } else {
53866  /* Note: array entries are always writable, so the writability check
53867  * above is pointless for them. The check could be avoided with some
53868  * refactoring but is probably not worth it.
53869  */
53870 
53871  DUK_ASSERT(desc.a_idx >= 0);
53872  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
53873  DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
53874  DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val); /* side effects; a_idx may be invalidated */
53875  DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
53876  (long) desc.a_idx, (duk_tval *) tv));
53877  }
53878 
53879  /* Regardless of whether property is found in entry or array part,
53880  * it may have arguments exotic behavior (array indices may reside
53881  * in entry part for abandoned / non-existent array parts).
53882  */
53883  goto success_with_arguments_exotic;
53884 
53885  create_new:
53886 
53887  /*
53888  * Create a new property in the original object.
53889  *
53890  * Exotic properties need to be reconsidered here from a write
53891  * perspective (not just property attributes perspective).
53892  * However, the property does not exist in the object already,
53893  * so this limits the kind of exotic properties that apply.
53894  */
53895 
53896  /* [key] */
53897 
53898  DUK_DDD(DUK_DDDPRINT("create new property to original object"));
53899 
53900  DUK_ASSERT(orig != NULL);
53901 
53902  /* Array own property .length is handled above. */
53903  DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
53904 
53905 #if defined(DUK_USE_ROM_OBJECTS)
53906  /* This should not happen because DUK_TAG_OBJECT case checks
53907  * for this already, but check just in case.
53908  */
53909  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
53910  goto fail_not_writable;
53911  }
53912 #endif
53913 
53914  /* Not possible because array object 'length' is present
53915  * from its creation and cannot be deleted, and is thus
53916  * caught as an existing property above.
53917  */
53918  DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
53919  key == DUK_HTHREAD_STRING_LENGTH(thr)));
53920 
53921  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
53922  arr_idx != DUK__NO_ARRAY_INDEX) {
53923  /* automatic length update */
53924  duk_uint32_t old_len;
53925  duk_harray *a;
53926 
53927  a = (duk_harray *) orig;
53928  DUK_ASSERT_HARRAY_VALID(a);
53929 
53930  old_len = a->length;
53931 
53932  if (arr_idx >= old_len) {
53933  DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
53934  "(arr_idx=%ld, old_len=%ld)",
53935  (long) arr_idx, (long) old_len));
53936 
53937  if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
53938  DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
53939  goto fail_not_writable;
53940  }
53941 
53942  /* Note: actual update happens once write has been completed
53943  * without error below. The write should always succeed
53944  * from a specification viewpoint, but we may e.g. run out
53945  * of memory. It's safer in this order.
53946  */
53947 
53948  DUK_ASSERT(arr_idx != 0xffffffffUL);
53949  new_array_length = arr_idx + 1; /* flag for later write */
53950  } else {
53951  DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
53952  "(arr_idx=%ld, old_len=%ld)",
53953  (long) arr_idx, (long) old_len));
53954  }
53955  }
53956 
53957  /* write_to_array_part: */
53958 
53959  /*
53960  * Write to array part?
53961  *
53962  * Note: array abandonding requires a property resize which uses
53963  * 'rechecks' valstack for temporaries and may cause any existing
53964  * valstack pointers to be invalidated. To protect against this,
53965  * tv_obj, tv_key, and tv_val are copies of the original inputs.
53966  */
53967 
53968  if (arr_idx != DUK__NO_ARRAY_INDEX &&
53969  DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
53970  if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
53971  goto no_array_growth;
53972  }
53973 
53974  /*
53975  * Array needs to grow, but we don't want it becoming too sparse.
53976  * If it were to become sparse, abandon array part, moving all
53977  * array entries into the entries part (for good).
53978  *
53979  * Since we don't keep track of actual density (used vs. size) of
53980  * the array part, we need to estimate somehow. The check is made
53981  * in two parts:
53982  *
53983  * - Check whether the resize need is small compared to the
53984  * current size (relatively); if so, resize without further
53985  * checking (essentially we assume that the original part is
53986  * "dense" so that the result would be dense enough).
53987  *
53988  * - Otherwise, compute the resize using an actual density
53989  * measurement based on counting the used array entries.
53990  */
53991 
53992  DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
53993  "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
53994  (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
53995 
53996  if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
53997  duk_uint32_t old_used;
53998  duk_uint32_t old_size;
53999 
54000  DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
54001 
54002  duk__compute_a_stats(thr, orig, &old_used, &old_size);
54003 
54004  DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
54005  (long) old_used, (long) old_size, (long) arr_idx));
54006 
54007  /* Note: intentionally use approximations to shave a few instructions:
54008  * a_used = old_used (accurate: old_used + 1)
54009  * a_size = arr_idx (accurate: arr_idx + 1)
54010  */
54011  if (duk__abandon_array_density_check(old_used, arr_idx)) {
54012  DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
54013  "decided to abandon array part (would become too sparse)"));
54014 
54015  /* abandoning requires a props allocation resize and
54016  * 'rechecks' the valstack, invalidating any existing
54017  * valstack value pointers!
54018  */
54019  duk__abandon_array_checked(thr, orig);
54020  DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
54021 
54022  goto write_to_entry_part;
54023  }
54024 
54025  DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
54026  } else {
54027  DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
54028  }
54029 
54030  DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
54031  "decided to extend current allocation"));
54032 
54033  duk__grow_props_for_array_item(thr, orig, arr_idx);
54034 
54035  no_array_growth:
54036 
54037  /* Note: assume array part is comprehensive, so that either
54038  * the write goes to the array part, or we've abandoned the
54039  * array above (and will not come here).
54040  */
54041 
54042  DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
54043  DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
54044 
54045  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
54046  /* prev value must be unused, no decref */
54047  DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
54048  DUK_TVAL_SET_TVAL(tv, tv_val);
54049  DUK_TVAL_INCREF(thr, tv);
54050  DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
54051  (long) arr_idx, (duk_tval *) tv));
54052 
54053  /* Note: array part values are [[Writable]], [[Enumerable]],
54054  * and [[Configurable]] which matches the required attributes
54055  * here.
54056  */
54057  goto entry_updated;
54058  }
54059 
54060  write_to_entry_part:
54061 
54062  /*
54063  * Write to entry part
54064  */
54065 
54066  /* entry allocation updates hash part and increases the key
54067  * refcount; may need a props allocation resize but doesn't
54068  * 'recheck' the valstack.
54069  */
54070  e_idx = duk__alloc_entry_checked(thr, orig, key);
54071  DUK_ASSERT(e_idx >= 0);
54072 
54073  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
54074  /* prev value can be garbage, no decref */
54075  DUK_TVAL_SET_TVAL(tv, tv_val);
54076  DUK_TVAL_INCREF(thr, tv);
54077  DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
54078  goto entry_updated;
54079 
54080  entry_updated:
54081 
54082  /*
54083  * Possible pending array length update, which must only be done
54084  * if the actual entry write succeeded.
54085  */
54086 
54087  if (new_array_length > 0) {
54088  /* Note: zero works as a "no update" marker because the new length
54089  * can never be zero after a new property is written.
54090  */
54091 
54092  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
54093 
54094  DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
54095  (long) new_array_length));
54096 
54097  ((duk_harray *) orig)->length = new_array_length;
54098  }
54099 
54100  /*
54101  * Arguments exotic behavior not possible for new properties: all
54102  * magically bound properties are initially present in the arguments
54103  * object, and if they are deleted, the binding is also removed from
54104  * parameter map.
54105  */
54106 
54107  goto success_no_arguments_exotic;
54108 
54109  success_with_arguments_exotic:
54110 
54111  /*
54112  * Arguments objects have exotic [[DefineOwnProperty]] which updates
54113  * the internal 'map' of arguments for writes to currently mapped
54114  * arguments. More conretely, writes to mapped arguments generate
54115  * a write to a bound variable.
54116  *
54117  * The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
54118  * data properties and new properties, but not for existing accessors.
54119  * Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
54120  * have a Desc with 'Value' (and possibly other properties too), and
54121  * we end up in step 5.b.i.
54122  */
54123 
54124  if (arr_idx != DUK__NO_ARRAY_INDEX &&
54125  DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
54126  /* Note: only numbered indices are relevant, so arr_idx fast reject
54127  * is good (this is valid unless there are more than 4**32-1 arguments).
54128  */
54129 
54130  DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
54131 
54132  /* Note: we can reuse 'desc' here */
54133 
54134  /* XXX: top of stack must contain value, which helper doesn't touch,
54135  * rework to use tv_val directly?
54136  */
54137 
54138  duk_push_tval(ctx, tv_val);
54139  (void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
54140  duk_pop(ctx);
54141  }
54142  /* fall thru */
54143 
54144  success_no_arguments_exotic:
54145  /* shared exit path now */
54146  DUK_DDD(DUK_DDDPRINT("result: success"));
54147  duk_pop(ctx); /* remove key */
54148  return 1;
54149 
54150 #if defined(DUK_USE_ES6_PROXY)
54151  fail_proxy_rejected:
54152  DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
54153  if (throw_flag) {
54154  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
54155  }
54156  /* Note: no key on stack */
54157  return 0;
54158 #endif
54159 
54160  fail_base_primitive:
54161  DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
54162  if (throw_flag) {
54163 #if defined(DUK_USE_PARANOID_ERRORS)
54164  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
54165 #else
54166  DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
54167  duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
54168 #endif
54169  }
54170  duk_pop(ctx); /* remove key */
54171  return 0;
54172 
54173  fail_not_extensible:
54174  DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
54175  if (throw_flag) {
54176  DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
54177  }
54178  duk_pop(ctx); /* remove key */
54179  return 0;
54180 
54181  fail_not_writable:
54182  DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
54183  if (throw_flag) {
54184  DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
54185  }
54186  duk_pop(ctx); /* remove key */
54187  return 0;
54188 
54189 #if defined(DUK_USE_ROM_OBJECTS)
54190  fail_not_writable_no_pop:
54191  DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
54192  if (throw_flag) {
54193  DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
54194  }
54195  return 0;
54196 #endif
54197 
54198  fail_array_length_partial:
54199  DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
54200  if (throw_flag) {
54201  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
54202  }
54203  duk_pop(ctx); /* remove key */
54204  return 0;
54205 
54206  fail_no_setter:
54207  DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
54208  if (throw_flag) {
54209  DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
54210  }
54211  duk_pop(ctx); /* remove key */
54212  return 0;
54213 
54214  fail_internal:
54215  DUK_DDD(DUK_DDDPRINT("result: error, internal"));
54216  if (throw_flag) {
54217  DUK_ERROR_INTERNAL(thr);
54218  }
54219  duk_pop(ctx); /* remove key */
54220  return 0;
54221 }
54222 
54223 /*
54224  * Ecmascript compliant [[Delete]](P, Throw).
54225  */
54226 
54227 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
54228  duk_propdesc desc;
54229  duk_tval *tv;
54230  duk_uint32_t arr_idx;
54231  duk_bool_t throw_flag;
54232  duk_bool_t force_flag;
54233 
54234  throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
54235  force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
54236 
54237  DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
54238  (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
54239  (duk_heaphdr *) obj, (duk_heaphdr *) key));
54240 
54241  DUK_ASSERT(thr != NULL);
54242  DUK_ASSERT(thr->heap != NULL);
54243  DUK_ASSERT(obj != NULL);
54244  DUK_ASSERT(key != NULL);
54245 
54246  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54247 
54248  arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
54249 
54250  /* 0 = don't push current value */
54251  if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
54252  DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
54253  goto success;
54254  }
54255 
54256 #if defined(DUK_USE_ROM_OBJECTS)
54257  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
54258  DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
54259  goto fail_not_configurable;
54260  }
54261 #endif
54262 
54263  if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
54264  goto fail_not_configurable;
54265  }
54266  if (desc.a_idx < 0 && desc.e_idx < 0) {
54267  /* Currently there are no deletable virtual properties, but
54268  * with force_flag we might attempt to delete one.
54269  */
54270  DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
54271  goto fail_virtual;
54272  }
54273 
54274  if (desc.a_idx >= 0) {
54275  DUK_ASSERT(desc.e_idx < 0);
54276 
54277  tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
54278  DUK_TVAL_SET_UNUSED_UPDREF(thr, tv); /* side effects */
54279  goto success;
54280  } else {
54281  DUK_ASSERT(desc.a_idx < 0);
54282 
54283  /* remove hash entry (no decref) */
54284 #if defined(DUK_USE_HOBJECT_HASH_PART)
54285  if (desc.h_idx >= 0) {
54286  duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
54287 
54288  DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
54289  DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
54290  DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
54291  h_base[desc.h_idx] = DUK__HASH_DELETED;
54292  } else {
54293  DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
54294  }
54295 #else
54296  DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
54297 #endif
54298 
54299  /* Remove value. This requires multiple writes so avoid side
54300  * effects via no-refzero macros so that e_idx is not
54301  * invalidated.
54302  */
54303  DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
54304  (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
54305  DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
54306  if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
54307  duk_hobject *tmp;
54308 
54309  tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
54310  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
54311  DUK_UNREF(tmp);
54312  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
54313 
54314  tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
54315  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
54316  DUK_UNREF(tmp);
54317  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
54318  } else {
54319  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
54320  DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
54321  }
54322 #if 0
54323  /* Not strictly necessary because if key == NULL, flag MUST be ignored. */
54324  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
54325 #endif
54326 
54327  /* Remove key. */
54328  DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
54329  (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
54330  DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
54331  DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
54332  DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
54333  DUK_HSTRING_DECREF_NORZ(thr, key);
54334 
54335  /* Trigger refzero side effects only when we're done as a
54336  * finalizer might operate on the object and affect the
54337  * e_idx we're supposed to use.
54338  */
54339  DUK_REFZERO_CHECK_SLOW(thr);
54340  goto success;
54341  }
54342 
54343  DUK_UNREACHABLE();
54344 
54345  success:
54346  /*
54347  * Argument exotic [[Delete]] behavior (E5 Section 10.6) is
54348  * a post-check, keeping arguments internal 'map' in sync with
54349  * any successful deletes (note that property does not need to
54350  * exist for delete to 'succeed').
54351  *
54352  * Delete key from 'map'. Since 'map' only contains array index
54353  * keys, we can use arr_idx for a fast skip.
54354  */
54355 
54356  DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
54357 
54358  if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
54359  /* Note: only numbered indices are relevant, so arr_idx fast reject
54360  * is good (this is valid unless there are more than 4**32-1 arguments).
54361  */
54362 
54363  DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
54364 
54365  /* Note: we can reuse 'desc' here */
54366  (void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
54367  }
54368 
54369  DUK_DDD(DUK_DDDPRINT("delete successful"));
54370  return 1;
54371 
54372  fail_virtual: /* just use the same "not configurable" error message */
54373  fail_not_configurable:
54374  DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
54375 
54376  if (throw_flag) {
54377  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
54378  }
54379  return 0;
54380 }
54381 
54382 /*
54383  * DELPROP: Ecmascript property deletion.
54384  */
54385 
54386 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
54387  duk_context *ctx = (duk_context *) thr;
54388  duk_hstring *key = NULL;
54389 #if defined(DUK_USE_ES6_PROXY)
54390  duk_propdesc desc;
54391 #endif
54392  duk_int_t entry_top;
54393  duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
54394  duk_bool_t rc;
54395 
54396  DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
54397  (void *) thr, (void *) tv_obj, (void *) tv_key,
54398  (duk_tval *) tv_obj, (duk_tval *) tv_key));
54399 
54400  DUK_ASSERT(ctx != NULL);
54401  DUK_ASSERT(thr != NULL);
54402  DUK_ASSERT(thr->heap != NULL);
54403  DUK_ASSERT(tv_obj != NULL);
54404  DUK_ASSERT(tv_key != NULL);
54405 
54406  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54407 
54408  /* Storing the entry top is cheaper here to ensure stack is correct at exit,
54409  * as there are several paths out.
54410  */
54411  entry_top = duk_get_top(ctx);
54412 
54413  if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
54414  DUK_TVAL_IS_NULL(tv_obj)) {
54415  DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
54416  goto fail_invalid_base_uncond;
54417  }
54418 
54419  duk_push_tval(ctx, tv_obj);
54420  duk_push_tval(ctx, tv_key);
54421 
54422  tv_obj = DUK_GET_TVAL_NEGIDX(ctx, -2);
54423  if (DUK_TVAL_IS_OBJECT(tv_obj)) {
54424  duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
54425  DUK_ASSERT(obj != NULL);
54426 
54427 #if defined(DUK_USE_ES6_PROXY)
54428  if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(obj))) {
54429  duk_hobject *h_target;
54430  duk_bool_t tmp_bool;
54431 
54432  /* Note: proxy handling must happen before key is string coerced. */
54433 
54434  if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
54435  /* -> [ ... trap handler ] */
54436  DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
54437  duk_push_hobject(ctx, h_target); /* target */
54438  duk_push_tval(ctx, tv_key); /* P */
54439  duk_call_method(ctx, 2 /*nargs*/);
54440  tmp_bool = duk_to_boolean(ctx, -1);
54441  duk_pop(ctx);
54442  if (!tmp_bool) {
54443  goto fail_proxy_rejected; /* retval indicates delete failed */
54444  }
54445 
54446  /* Target object must be checked for a conflicting
54447  * non-configurable property.
54448  */
54449  arr_idx = duk__push_tval_to_property_key(ctx, tv_key, &key);
54450  DUK_ASSERT(key != NULL);
54451 
54452  if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
54453  duk_small_int_t desc_reject;
54454 
54455  DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
54456  "conflicting property; desc.flags=0x%08lx, "
54457  "desc.get=%p, desc.set=%p",
54458  (duk_heaphdr *) key, (unsigned long) desc.flags,
54459  (void *) desc.get, (void *) desc.set));
54460 
54461  desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
54462  if (desc_reject) {
54463  /* unconditional */
54464  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
54465  }
54466  }
54467  rc = 1; /* success */
54468  goto done_rc;
54469  }
54470 
54471  obj = h_target; /* resume delete to target */
54472  }
54473 #endif /* DUK_USE_ES6_PROXY */
54474 
54475  arr_idx = duk__to_property_key(ctx, -1, &key);
54476  DUK_ASSERT(key != NULL);
54477 
54478  rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
54479  goto done_rc;
54480  } else if (DUK_TVAL_IS_STRING(tv_obj)) {
54481  /* String has .length and array index virtual properties
54482  * which can't be deleted. No need for a symbol check;
54483  * no offending virtual symbols exist.
54484  */
54485  /* XXX: unnecessary string coercion for array indices,
54486  * intentional to keep small.
54487  */
54488  duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
54489  DUK_ASSERT(h != NULL);
54490 
54491  arr_idx = duk__to_property_key(ctx, -1, &key);
54492  DUK_ASSERT(key != NULL);
54493 
54494  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
54495  goto fail_not_configurable;
54496  }
54497 
54498  if (arr_idx != DUK__NO_ARRAY_INDEX &&
54499  arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
54500  goto fail_not_configurable;
54501  }
54502  } else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
54503  /* XXX: unnecessary string coercion for array indices,
54504  * intentional to keep small; some overlap with string
54505  * handling.
54506  */
54507  duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
54508  DUK_ASSERT(h != NULL);
54509 
54510  arr_idx = duk__to_property_key(ctx, -1, &key);
54511  DUK_ASSERT(key != NULL);
54512 
54513  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
54514  goto fail_not_configurable;
54515  }
54516 
54517  if (arr_idx != DUK__NO_ARRAY_INDEX &&
54518  arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
54519  goto fail_not_configurable;
54520  }
54521  } else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
54522  /* Lightfunc virtual properties are non-configurable, so
54523  * reject if match any of them.
54524  */
54525 
54526  arr_idx = duk__to_property_key(ctx, -1, &key);
54527  DUK_ASSERT(key != NULL);
54528 
54529  if (duk__key_is_lightfunc_ownprop(thr, key)) {
54530  goto fail_not_configurable;
54531  }
54532  }
54533 
54534  /* non-object base, no offending virtual property */
54535  rc = 1;
54536  goto done_rc;
54537 
54538  done_rc:
54539  duk_set_top(ctx, entry_top);
54540  return rc;
54541 
54542  fail_invalid_base_uncond:
54543  /* Note: unconditional throw */
54544  DUK_ASSERT(duk_get_top(ctx) == entry_top);
54545 #if defined(DUK_USE_PARANOID_ERRORS)
54546  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
54547 #else
54548  DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
54549  duk_push_string_tval_readable(ctx, tv_key), duk_push_string_tval_readable(ctx, tv_obj));
54550 #endif
54551  return 0;
54552 
54553 #if defined(DUK_USE_ES6_PROXY)
54554  fail_proxy_rejected:
54555  if (throw_flag) {
54556  DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
54557  }
54558  duk_set_top(ctx, entry_top);
54559  return 0;
54560 #endif
54561 
54562  fail_not_configurable:
54563  if (throw_flag) {
54564  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
54565  }
54566  duk_set_top(ctx, entry_top);
54567  return 0;
54568 }
54569 
54570 /*
54571  * Internal helper to define a property with specific flags, ignoring
54572  * normal semantics such as extensibility, write protection etc.
54573  * Overwrites any existing value and attributes unless caller requests
54574  * that value only be updated if it doesn't already exists.
54575  *
54576  * Does not support:
54577  * - virtual properties (error if write attempted)
54578  * - getter/setter properties (error if write attempted)
54579  * - non-default (!= WEC) attributes for array entries (error if attempted)
54580  * - array abandoning: if array part exists, it is always extended
54581  * - array 'length' updating
54582  *
54583  * Stack: [... in_val] -> []
54584  *
54585  * Used for e.g. built-in initialization and environment record
54586  * operations.
54587  */
54588 
54589 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
54590  duk_context *ctx = (duk_context *) thr;
54591  duk_propdesc desc;
54592  duk_uint32_t arr_idx;
54593  duk_int_t e_idx;
54594  duk_tval *tv1 = NULL;
54595  duk_tval *tv2 = NULL;
54596  duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK; /* mask out flags not actually stored */
54597 
54598  DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
54599  (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
54600  (unsigned long) flags, (duk_tval *) duk_get_tval(ctx, -1)));
54601 
54602  DUK_ASSERT(thr != NULL);
54603  DUK_ASSERT(thr->heap != NULL);
54604  DUK_ASSERT(obj != NULL);
54605  DUK_ASSERT(key != NULL);
54606  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
54607  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54608  DUK_ASSERT(duk_is_valid_index(ctx, -1)); /* contains value */
54609 
54610  arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
54611 
54612  if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) { /* don't push value */
54613  if (desc.e_idx >= 0) {
54614  if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
54615  DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
54616  goto pop_exit;
54617  }
54618  DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
54619  if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
54620  DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
54621  goto error_internal;
54622  }
54623 
54624  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
54625  tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
54626  } else if (desc.a_idx >= 0) {
54627  if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
54628  DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
54629  goto pop_exit;
54630  }
54631  DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
54632  if (propflags != DUK_PROPDESC_FLAGS_WEC) {
54633  DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
54634  (unsigned long) propflags));
54635  goto error_internal;
54636  }
54637 
54638  tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
54639  } else {
54640  if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
54641  DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
54642  goto pop_exit;
54643  }
54644  if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
54645  duk_uint32_t new_len;
54646 #if defined(DUK_USE_DEBUG)
54647  duk_uint32_t prev_len;
54648  prev_len = ((duk_harray *) obj)->length;
54649 #endif
54650  new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(ctx, -1));
54651  ((duk_harray *) obj)->length = new_len;
54652  DUK_D(DUK_DPRINT("internal define property for array .length: %ld -> %ld",
54653  (long) prev_len, (long) ((duk_harray *) obj)->length));
54654  goto pop_exit;
54655  }
54656  DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
54657  goto error_virtual;
54658  }
54659 
54660  goto write_value;
54661  }
54662 
54663  if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
54664  if (arr_idx != DUK__NO_ARRAY_INDEX) {
54665  DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
54666  DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
54667 
54668  /* always grow the array, no sparse / abandon support here */
54669  if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
54670  duk__grow_props_for_array_item(thr, obj, arr_idx);
54671  }
54672 
54673  DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
54674  tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
54675  goto write_value;
54676  }
54677  }
54678 
54679  DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
54680  e_idx = duk__alloc_entry_checked(thr, obj, key); /* increases key refcount */
54681  DUK_ASSERT(e_idx >= 0);
54682  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
54683  tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
54684  /* new entry: previous value is garbage; set to undefined to share write_value */
54685  DUK_TVAL_SET_UNDEFINED(tv1);
54686  goto write_value;
54687 
54688  write_value:
54689  /* tv1 points to value storage */
54690 
54691  tv2 = duk_require_tval(ctx, -1); /* late lookup, avoid side effects */
54692  DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
54693  (duk_tval *) tv1, (duk_tval *) tv2));
54694 
54695  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
54696  goto pop_exit;
54697 
54698  pop_exit:
54699  duk_pop(ctx); /* remove in_val */
54700  return;
54701 
54702  error_virtual: /* share error message */
54703  error_internal:
54704  DUK_ERROR_INTERNAL(thr);
54705  return;
54706 }
54707 
54708 /*
54709  * Fast path for defining array indexed values without interning the key.
54710  * This is used by e.g. code for Array prototype and traceback creation so
54711  * must avoid interning.
54712  */
54713 
54714 DUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {
54715  duk_context *ctx = (duk_context *) thr;
54716  duk_hstring *key;
54717  duk_tval *tv1, *tv2;
54718 
54719  DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
54720  "arr_idx=%ld, flags=0x%02lx, val=%!T",
54721  (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
54722  (duk_tval *) duk_get_tval(ctx, -1)));
54723 
54724  DUK_ASSERT(thr != NULL);
54725  DUK_ASSERT(thr->heap != NULL);
54726  DUK_ASSERT(obj != NULL);
54727  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
54728 
54729  if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
54730  arr_idx != DUK__NO_ARRAY_INDEX &&
54731  flags == DUK_PROPDESC_FLAGS_WEC) {
54732  DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0); /* covered by comparison */
54733 
54734  DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
54735 
54736  /* always grow the array, no sparse / abandon support here */
54737  if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
54738  duk__grow_props_for_array_item(thr, obj, arr_idx);
54739  }
54740 
54741  DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
54742  tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
54743  tv2 = duk_require_tval(ctx, -1);
54744 
54745  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
54746 
54747  duk_pop(ctx); /* [ ...val ] -> [ ... ] */
54748  return;
54749  }
54750 
54751  DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
54752 
54753  key = duk_push_uint_to_hstring(ctx, (duk_uint_t) arr_idx);
54754  DUK_ASSERT(key != NULL);
54755  duk_insert(ctx, -2); /* [ ... val key ] -> [ ... key val ] */
54756 
54757  duk_hobject_define_property_internal(thr, obj, key, flags);
54758 
54759  duk_pop(ctx); /* [ ... key ] -> [ ... ] */
54760 }
54761 
54762 /*
54763  * Internal helpers for managing object 'length'
54764  */
54765 
54766 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
54767  duk_context *ctx = (duk_context *) thr;
54768  duk_double_t val;
54769 
54770  DUK_ASSERT_CTX_VALID(ctx);
54771  DUK_ASSERT(obj != NULL);
54772 
54773  /* Fast path for Arrays. */
54774  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
54775  return ((duk_harray *) obj)->length;
54776  }
54777 
54778  /* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
54779  duk_push_hobject(ctx, obj);
54780  duk_push_hstring_stridx(ctx, DUK_STRIDX_LENGTH);
54781  (void) duk_hobject_getprop(thr,
54782  DUK_GET_TVAL_NEGIDX(ctx, -2),
54783  DUK_GET_TVAL_NEGIDX(ctx, -1));
54784  val = duk_to_number_m1(ctx);
54785  duk_pop_3(ctx);
54786 
54787  /* This isn't part of Ecmascript semantics; return a value within
54788  * duk_size_t range, or 0 otherwise.
54789  */
54790  if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
54791  return (duk_size_t) val;
54792  }
54793  return 0;
54794 }
54795 
54796 /*
54797  * Object.getOwnPropertyDescriptor() (E5 Sections 15.2.3.3, 8.10.4)
54798  *
54799  * [ ... key ] -> [ ... desc/undefined ]
54800  */
54801 
54802 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_context *ctx, duk_idx_t obj_idx) {
54803  duk_hthread *thr = (duk_hthread *) ctx;
54804  duk_hobject *obj;
54805  duk_hstring *key;
54806  duk_propdesc pd;
54807  duk_bool_t rc;
54808 
54809  DUK_ASSERT(ctx != NULL);
54810  DUK_ASSERT(thr != NULL);
54811  DUK_ASSERT(thr->heap != NULL);
54812 
54813  obj = duk_require_hobject_promote_mask(ctx, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
54814  key = duk_to_property_key_hstring(ctx, -1);
54815  DUK_ASSERT(key != NULL);
54816 
54817  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54818 
54819  rc = duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE);
54820  if (!rc) {
54821  duk_push_undefined(ctx);
54822  duk_remove_m2(ctx);
54823  return;
54824  }
54825 
54826  duk_push_object(ctx);
54827 
54828  /* [ ... key value desc ] */
54829 
54830  if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
54831  /* If a setter/getter is missing (undefined), the descriptor must
54832  * still have the property present with the value 'undefined'.
54833  */
54834  if (pd.get) {
54835  duk_push_hobject(ctx, pd.get);
54836  } else {
54837  duk_push_undefined(ctx);
54838  }
54839  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_GET);
54840  if (pd.set) {
54841  duk_push_hobject(ctx, pd.set);
54842  } else {
54843  duk_push_undefined(ctx);
54844  }
54845  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_SET);
54846  } else {
54847  duk_dup_m2(ctx);
54848  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_VALUE);
54849  duk_push_boolean(ctx, DUK_PROPDESC_IS_WRITABLE(&pd));
54850  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_WRITABLE);
54851  }
54852  duk_push_boolean(ctx, DUK_PROPDESC_IS_ENUMERABLE(&pd));
54853  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_ENUMERABLE);
54854  duk_push_boolean(ctx, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
54855  duk_put_prop_stridx_short(ctx, -2, DUK_STRIDX_CONFIGURABLE);
54856 
54857  /* [ ... key value desc ] */
54858 
54859  duk_replace(ctx, -3);
54860  duk_pop(ctx); /* -> [ ... desc ] */
54861 }
54862 
54863 /*
54864  * NormalizePropertyDescriptor() related helper.
54865  *
54866  * Internal helper which validates and normalizes a property descriptor
54867  * represented as an Ecmascript object (e.g. argument to defineProperty()).
54868  * The output of this conversion is a set of defprop_flags and possibly
54869  * some values pushed on the value stack to (1) ensure borrowed pointers
54870  * remain valid, and (2) avoid unnecessary pops for footprint reasons.
54871  * Caller must manage stack top carefully because the number of values
54872  * pushed depends on the input property descriptor.
54873  *
54874  * The original descriptor object must not be altered in the process.
54875  */
54876 
54877 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
54878 
54879 DUK_INTERNAL
54880 void duk_hobject_prepare_property_descriptor(duk_context *ctx,
54881  duk_idx_t idx_in,
54882  duk_uint_t *out_defprop_flags,
54883  duk_idx_t *out_idx_value,
54884  duk_hobject **out_getter,
54885  duk_hobject **out_setter) {
54886  duk_hthread *thr = (duk_hthread *) ctx;
54887  duk_idx_t idx_value = -1;
54888  duk_hobject *getter = NULL;
54889  duk_hobject *setter = NULL;
54890  duk_bool_t is_data_desc = 0;
54891  duk_bool_t is_acc_desc = 0;
54892  duk_uint_t defprop_flags = 0;
54893 
54894  DUK_ASSERT(ctx != NULL);
54895  DUK_ASSERT(out_defprop_flags != NULL);
54896  DUK_ASSERT(out_idx_value != NULL);
54897  DUK_ASSERT(out_getter != NULL);
54898  DUK_ASSERT(out_setter != NULL);
54899  DUK_ASSERT(idx_in <= 0x7fffL); /* short variants would be OK, but not used to avoid shifts */
54900 
54901  /* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
54902  idx_in = duk_require_normalize_index(ctx, idx_in);
54903  (void) duk_require_hobject(ctx, idx_in);
54904 
54905  /* The coercion order must match the ToPropertyDescriptor() algorithm
54906  * so that side effects in coercion happen in the correct order.
54907  * (This order also happens to be compatible with duk_def_prop(),
54908  * although it doesn't matter in practice.)
54909  */
54910 
54911  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_VALUE)) {
54912  is_data_desc = 1;
54913  defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
54914  idx_value = duk_get_top_index(ctx);
54915  }
54916 
54917  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_WRITABLE)) {
54918  is_data_desc = 1;
54919  if (duk_to_boolean(ctx, -1)) {
54920  defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
54921  } else {
54922  defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
54923  }
54924  }
54925 
54926  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_GET)) {
54927  duk_tval *tv = duk_require_tval(ctx, -1);
54928  duk_hobject *h_get;
54929 
54930  if (DUK_TVAL_IS_UNDEFINED(tv)) {
54931  /* undefined is accepted */
54932  DUK_ASSERT(getter == NULL);
54933  } else {
54934  /* NOTE: lightfuncs are coerced to full functions because
54935  * lightfuncs don't fit into a property value slot. This
54936  * has some side effects, see test-dev-lightfunc-accessor.js.
54937  */
54938  h_get = duk_get_hobject_promote_lfunc(ctx, -1);
54939  if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
54940  goto type_error;
54941  }
54942  getter = h_get;
54943  }
54944  is_acc_desc = 1;
54945  defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
54946  }
54947 
54948  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_SET)) {
54949  duk_tval *tv = duk_require_tval(ctx, -1);
54950  duk_hobject *h_set;
54951 
54952  if (DUK_TVAL_IS_UNDEFINED(tv)) {
54953  /* undefined is accepted */
54954  DUK_ASSERT(setter == NULL);
54955  } else {
54956  /* NOTE: lightfuncs are coerced to full functions because
54957  * lightfuncs don't fit into a property value slot. This
54958  * has some side effects, see test-dev-lightfunc-accessor.js.
54959  */
54960  h_set = duk_get_hobject_promote_lfunc(ctx, -1);
54961  if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
54962  goto type_error;
54963  }
54964  setter = h_set;
54965  }
54966  is_acc_desc = 1;
54967  defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
54968  }
54969 
54970  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_ENUMERABLE)) {
54971  if (duk_to_boolean(ctx, -1)) {
54972  defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
54973  } else {
54974  defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
54975  }
54976  }
54977 
54978  if (duk_get_prop_stridx(ctx, idx_in, DUK_STRIDX_CONFIGURABLE)) {
54979  if (duk_to_boolean(ctx, -1)) {
54980  defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
54981  } else {
54982  defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
54983  }
54984  }
54985 
54986  if (is_data_desc && is_acc_desc) {
54987  goto type_error;
54988  }
54989 
54990  *out_defprop_flags = defprop_flags;
54991  *out_idx_value = idx_value;
54992  *out_getter = getter;
54993  *out_setter = setter;
54994 
54995  /* [ ... [multiple values] ] */
54996  return;
54997 
54998  type_error:
54999  DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
55000 }
55001 
55002 /*
55003  * Object.defineProperty() related helper (E5 Section 15.2.3.6).
55004  * Also handles ES2015 Reflect.defineProperty().
55005  *
55006  * Inlines all [[DefineOwnProperty]] exotic behaviors.
55007  *
55008  * Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
55009  * implemented directly, but Object.defineProperty() serves its purpose.
55010  * We don't need the [[DefineOwnProperty]] internally and we don't have a
55011  * property descriptor with 'missing values' so it's easier to avoid it
55012  * entirely.
55013  *
55014  * Note: this is only called for actual objects, not primitive values.
55015  * This must support virtual properties for full objects (e.g. Strings)
55016  * but not for plain values (e.g. strings). Lightfuncs, even though
55017  * primitive in a sense, are treated like objects and accepted as target
55018  * values.
55019  */
55020 
55021 /* XXX: this is a major target for size optimization */
55022 DUK_INTERNAL
55023 duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
55024  duk_uint_t defprop_flags,
55025  duk_hobject *obj,
55026  duk_hstring *key,
55027  duk_idx_t idx_value,
55028  duk_hobject *get,
55029  duk_hobject *set,
55030  duk_bool_t throw_flag) {
55031  duk_hthread *thr = (duk_hthread *) ctx;
55032  duk_uint32_t arr_idx;
55033  duk_tval tv;
55034  duk_bool_t has_enumerable;
55035  duk_bool_t has_configurable;
55036  duk_bool_t has_writable;
55037  duk_bool_t has_value;
55038  duk_bool_t has_get;
55039  duk_bool_t has_set;
55040  duk_bool_t is_enumerable;
55041  duk_bool_t is_configurable;
55042  duk_bool_t is_writable;
55043  duk_bool_t force_flag;
55044  duk_small_uint_t new_flags;
55045  duk_propdesc curr;
55046  duk_uint32_t arridx_new_array_length; /* != 0 => post-update for array 'length' (used when key is an array index) */
55047  duk_uint32_t arrlen_old_len;
55048  duk_uint32_t arrlen_new_len;
55049  duk_bool_t pending_write_protect;
55050 
55051  DUK_ASSERT(thr != NULL);
55052  DUK_ASSERT(thr->heap != NULL);
55053  DUK_ASSERT(ctx != NULL);
55054  DUK_ASSERT(obj != NULL);
55055  DUK_ASSERT(key != NULL);
55056  /* idx_value may be < 0 (no value), set and get may be NULL */
55057 
55058  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55059 
55060  /* All the flags fit in 16 bits, so will fit into duk_bool_t. */
55061 
55062  has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
55063  has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
55064  has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
55065  has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
55066  has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
55067  has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
55068  is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
55069  is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
55070  is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
55071  force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
55072 
55073  arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
55074 
55075  arridx_new_array_length = 0;
55076  pending_write_protect = 0;
55077  arrlen_old_len = 0;
55078  arrlen_new_len = 0;
55079 
55080  DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
55081  "has_configurable=%ld is_configurable=%ld "
55082  "has_writable=%ld is_writable=%ld "
55083  "has_value=%ld value=%!T "
55084  "has_get=%ld get=%p=%!O "
55085  "has_set=%ld set=%p=%!O "
55086  "arr_idx=%ld throw_flag=!%ld",
55087  (long) has_enumerable, (long) is_enumerable,
55088  (long) has_configurable, (long) is_configurable,
55089  (long) has_writable, (long) is_writable,
55090  (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(ctx, idx_value) : NULL),
55091  (long) has_get, (void *) get, (duk_heaphdr *) get,
55092  (long) has_set, (void *) set, (duk_heaphdr *) set,
55093  (long) arr_idx, (long) throw_flag));
55094 
55095  /*
55096  * Array exotic behaviors can be implemented at this point. The local variables
55097  * are essentially a 'value copy' of the input descriptor (Desc), which is modified
55098  * by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
55099  */
55100 
55101  if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
55102  goto skip_array_exotic;
55103  }
55104 
55105  if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
55106  duk_harray *a;
55107 
55108  /* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
55109  if (!has_value) {
55110  DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
55111  goto skip_array_exotic;
55112  }
55113 
55114  DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
55115 
55116  /*
55117  * Get old and new length
55118  */
55119 
55120  a = (duk_harray *) obj;
55121  DUK_ASSERT_HARRAY_VALID(a);
55122  arrlen_old_len = a->length;
55123 
55124  DUK_ASSERT(idx_value >= 0);
55125  arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(ctx, idx_value));
55126  duk_push_u32(ctx, arrlen_new_len);
55127  duk_replace(ctx, idx_value); /* step 3.e: replace 'Desc.[[Value]]' */
55128 
55129  DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
55130 
55131  if (arrlen_new_len >= arrlen_old_len) {
55132  /* standard behavior, step 3.f.i */
55133  DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
55134  goto skip_array_exotic;
55135  }
55136  DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
55137 
55138  /* XXX: consolidated algorithm step 15.f -> redundant? */
55139  if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
55140  /* Array .length is always non-configurable; if it's also
55141  * non-writable, don't allow it to be written.
55142  */
55143  goto fail_not_configurable;
55144  }
55145 
55146  /* steps 3.h and 3.i */
55147  if (has_writable && !is_writable) {
55148  DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
55149  is_writable = 1;
55150  pending_write_protect = 1;
55151  }
55152 
55153  /* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
55154  } else if (arr_idx != DUK__NO_ARRAY_INDEX) {
55155  /* XXX: any chance of unifying this with the 'length' key handling? */
55156 
55157  /* E5 Section 15.4.5.1, step 4 */
55158  duk_uint32_t old_len;
55159  duk_harray *a;
55160 
55161  a = (duk_harray *) obj;
55162  DUK_ASSERT_HARRAY_VALID(a);
55163 
55164  old_len = a->length;
55165 
55166  if (arr_idx >= old_len) {
55167  DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
55168  "(arr_idx=%ld, old_len=%ld)",
55169  (long) arr_idx, (long) old_len));
55170 
55171  if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
55172  /* Array .length is always non-configurable, so
55173  * if it's also non-writable, don't allow a value
55174  * write. With force flag allow writing.
55175  */
55176  goto fail_not_configurable;
55177  }
55178 
55179  /* actual update happens once write has been completed without
55180  * error below.
55181  */
55182  DUK_ASSERT(arr_idx != 0xffffffffUL);
55183  arridx_new_array_length = arr_idx + 1;
55184  } else {
55185  DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
55186  "(arr_idx=%ld, old_len=%ld) -> standard behavior",
55187  (long) arr_idx, (long) old_len));
55188  }
55189  }
55190  skip_array_exotic:
55191 
55192  /* XXX: There is currently no support for writing buffer object
55193  * indexed elements here. Attempt to do so will succeed and
55194  * write a concrete property into the buffer object. This should
55195  * be fixed at some point but because buffers are a custom feature
55196  * anyway, this is relatively unimportant.
55197  */
55198 
55199  /*
55200  * Actual Object.defineProperty() default algorithm.
55201  */
55202 
55203  /*
55204  * First check whether property exists; if not, simple case. This covers
55205  * steps 1-4.
55206  */
55207 
55208  if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55209  DUK_DDD(DUK_DDDPRINT("property does not exist"));
55210 
55211  if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
55212  goto fail_not_extensible;
55213  }
55214 
55215 #if defined(DUK_USE_ROM_OBJECTS)
55216  /* ROM objects are never extensible but force flag may
55217  * allow us to come here anyway.
55218  */
55219  DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
55220  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55221  DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
55222  goto fail_not_configurable;
55223  }
55224 #endif
55225 
55226  /* XXX: share final setting code for value and flags? difficult because
55227  * refcount code is different. Share entry allocation? But can't allocate
55228  * until array index checked.
55229  */
55230 
55231  /* steps 4.a and 4.b are tricky */
55232  if (has_set || has_get) {
55233  duk_int_t e_idx;
55234 
55235  DUK_DDD(DUK_DDDPRINT("create new accessor property"));
55236 
55237  DUK_ASSERT(has_set || set == NULL);
55238  DUK_ASSERT(has_get || get == NULL);
55239  DUK_ASSERT(!has_value);
55240  DUK_ASSERT(!has_writable);
55241 
55242  new_flags = DUK_PROPDESC_FLAG_ACCESSOR; /* defaults, E5 Section 8.6.1, Table 7 */
55243  if (has_enumerable && is_enumerable) {
55244  new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
55245  }
55246  if (has_configurable && is_configurable) {
55247  new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
55248  }
55249 
55250  if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55251  DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
55252  duk__abandon_array_checked(thr, obj);
55253  }
55254 
55255  /* write to entry part */
55256  e_idx = duk__alloc_entry_checked(thr, obj, key);
55257  DUK_ASSERT(e_idx >= 0);
55258 
55259  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
55260  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
55261  DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
55262  DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
55263 
55264  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
55265  goto success_exotics;
55266  } else {
55267  duk_int_t e_idx;
55268  duk_tval *tv2;
55269 
55270  DUK_DDD(DUK_DDDPRINT("create new data property"));
55271 
55272  DUK_ASSERT(!has_set);
55273  DUK_ASSERT(!has_get);
55274 
55275  new_flags = 0; /* defaults, E5 Section 8.6.1, Table 7 */
55276  if (has_writable && is_writable) {
55277  new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
55278  }
55279  if (has_enumerable && is_enumerable) {
55280  new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
55281  }
55282  if (has_configurable && is_configurable) {
55283  new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
55284  }
55285  if (has_value) {
55286  duk_tval *tv_tmp = duk_require_tval(ctx, idx_value);
55287  DUK_TVAL_SET_TVAL(&tv, tv_tmp);
55288  } else {
55289  DUK_TVAL_SET_UNDEFINED(&tv); /* default value */
55290  }
55291 
55292  if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55293  if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
55294 #if 0
55295  DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
55296  /* may become sparse...*/
55297 #endif
55298  /* XXX: handling for array part missing now; this doesn't affect
55299  * compliance but causes array entry writes using defineProperty()
55300  * to always abandon array part.
55301  */
55302  }
55303  DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
55304  duk__abandon_array_checked(thr, obj);
55305  /* fall through */
55306  }
55307 
55308  /* write to entry part */
55309  e_idx = duk__alloc_entry_checked(thr, obj, key);
55310  DUK_ASSERT(e_idx >= 0);
55311  tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
55312  DUK_TVAL_SET_TVAL(tv2, &tv);
55313  DUK_TVAL_INCREF(thr, tv2);
55314 
55315  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
55316  goto success_exotics;
55317  }
55318  DUK_UNREACHABLE();
55319  }
55320 
55321  /* we currently assume virtual properties are not configurable (as none of them are) */
55322  DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
55323 
55324  /* [obj key desc value get set curr_value] */
55325 
55326  /*
55327  * Property already exists. Steps 5-6 detect whether any changes need
55328  * to be made.
55329  */
55330 
55331  if (has_enumerable) {
55332  if (is_enumerable) {
55333  if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
55334  goto need_check;
55335  }
55336  } else {
55337  if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
55338  goto need_check;
55339  }
55340  }
55341  }
55342  if (has_configurable) {
55343  if (is_configurable) {
55344  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
55345  goto need_check;
55346  }
55347  } else {
55348  if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
55349  goto need_check;
55350  }
55351  }
55352  }
55353  if (has_value) {
55354  duk_tval *tmp1;
55355  duk_tval *tmp2;
55356 
55357  /* attempt to change from accessor to data property */
55358  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55359  goto need_check;
55360  }
55361 
55362  tmp1 = duk_require_tval(ctx, -1); /* curr value */
55363  tmp2 = duk_require_tval(ctx, idx_value); /* new value */
55364  if (!duk_js_samevalue(tmp1, tmp2)) {
55365  goto need_check;
55366  }
55367  }
55368  if (has_writable) {
55369  /* attempt to change from accessor to data property */
55370  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55371  goto need_check;
55372  }
55373 
55374  if (is_writable) {
55375  if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
55376  goto need_check;
55377  }
55378  } else {
55379  if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
55380  goto need_check;
55381  }
55382  }
55383  }
55384  if (has_set) {
55385  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55386  if (set != curr.set) {
55387  goto need_check;
55388  }
55389  } else {
55390  goto need_check;
55391  }
55392  }
55393  if (has_get) {
55394  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55395  if (get != curr.get) {
55396  goto need_check;
55397  }
55398  } else {
55399  goto need_check;
55400  }
55401  }
55402 
55403  /* property exists, either 'desc' is empty, or all values
55404  * match (SameValue)
55405  */
55406  goto success_no_exotics;
55407 
55408  need_check:
55409 
55410  /*
55411  * Some change(s) need to be made. Steps 7-11.
55412  */
55413 
55414  /* shared checks for all descriptor types */
55415  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
55416  if (has_configurable && is_configurable) {
55417  goto fail_not_configurable;
55418  }
55419  if (has_enumerable) {
55420  if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
55421  if (!is_enumerable) {
55422  goto fail_not_configurable;
55423  }
55424  } else {
55425  if (is_enumerable) {
55426  goto fail_not_configurable;
55427  }
55428  }
55429  }
55430  }
55431 
55432  /* Virtual properties don't have backing so they can't mostly be
55433  * edited. Some virtual properties are, however, writable: for
55434  * example, virtual index properties of buffer objects and Array
55435  * instance .length. These are not configurable so the checks
55436  * above mostly cover attempts to change them, except when the
55437  * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
55438  * that case we can't forcibly change the property attributes
55439  * because they don't have concrete backing.
55440  */
55441 
55442  /* XXX: for ROM objects too it'd be best if value modify was
55443  * allowed if the value matches SameValue.
55444  */
55445  /* Reject attempt to change a read-only object. */
55446 #if defined(DUK_USE_ROM_OBJECTS)
55447  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55448  DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
55449  goto fail_not_configurable;
55450  }
55451 #endif
55452 
55453  /* descriptor type specific checks */
55454  if (has_set || has_get) {
55455  /* IsAccessorDescriptor(desc) == true */
55456  DUK_ASSERT(!has_writable);
55457  DUK_ASSERT(!has_value);
55458 
55459  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55460  /* curr and desc are accessors */
55461  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
55462  if (has_set && set != curr.set) {
55463  goto fail_not_configurable;
55464  }
55465  if (has_get && get != curr.get) {
55466  goto fail_not_configurable;
55467  }
55468  }
55469  } else {
55470  duk_bool_t rc;
55471  duk_tval *tv1;
55472 
55473  /* curr is data, desc is accessor */
55474  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
55475  goto fail_not_configurable;
55476  }
55477 
55478  DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
55479  if (curr.a_idx >= 0) {
55480  DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
55481  duk__abandon_array_checked(thr, obj);
55482  duk_pop(ctx); /* remove old value */
55483  rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
55484  DUK_UNREF(rc);
55485  DUK_ASSERT(rc != 0);
55486  DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
55487  }
55488  if (curr.e_idx < 0) {
55489  DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
55490  goto fail_virtual; /* safeguard for virtual property */
55491  }
55492 
55493  DUK_ASSERT(curr.e_idx >= 0);
55494  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
55495 
55496  tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
55497  DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1); /* XXX: just decref */
55498 
55499  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
55500  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
55501  DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
55502  DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
55503 
55504  DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
55505  (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
55506  /* Update curr.flags; faster than a re-lookup. */
55507  curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
55508  curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
55509  }
55510  } else if (has_value || has_writable) {
55511  /* IsDataDescriptor(desc) == true */
55512  DUK_ASSERT(!has_set);
55513  DUK_ASSERT(!has_get);
55514 
55515  if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
55516  duk_hobject *tmp;
55517 
55518  /* curr is accessor, desc is data */
55519  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
55520  goto fail_not_configurable;
55521  }
55522 
55523  /* curr is accessor -> cannot be in array part. */
55524  DUK_ASSERT(curr.a_idx < 0);
55525  if (curr.e_idx < 0) {
55526  goto fail_virtual; /* safeguard; no virtual accessors now */
55527  }
55528 
55529  DUK_DDD(DUK_DDDPRINT("convert property to data property"));
55530 
55531  DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
55532  tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
55533  DUK_UNREF(tmp);
55534  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
55535  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
55536  tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
55537  DUK_UNREF(tmp);
55538  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
55539  DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
55540 
55541  DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
55542  DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
55543  DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
55544 
55545  DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
55546  (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
55547 
55548  /* Update curr.flags; faster than a re-lookup. */
55549  curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
55550  } else {
55551  /* curr and desc are data */
55552  if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
55553  if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
55554  goto fail_not_configurable;
55555  }
55556  /* Note: changing from writable to non-writable is OK */
55557  if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
55558  duk_tval *tmp1 = duk_require_tval(ctx, -1); /* curr value */
55559  duk_tval *tmp2 = duk_require_tval(ctx, idx_value); /* new value */
55560  if (!duk_js_samevalue(tmp1, tmp2)) {
55561  goto fail_not_configurable;
55562  }
55563  }
55564  }
55565  }
55566  } else {
55567  /* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
55568  * only has [[Enumerable]] or [[Configurable]] flag updates, which are
55569  * allowed at this point.
55570  */
55571 
55572  DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
55573  }
55574 
55575  /*
55576  * Start doing property attributes updates. Steps 12-13.
55577  *
55578  * Start by computing new attribute flags without writing yet.
55579  * Property type conversion is done above if necessary.
55580  */
55581 
55582  new_flags = curr.flags;
55583 
55584  if (has_enumerable) {
55585  if (is_enumerable) {
55586  new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
55587  } else {
55588  new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
55589  }
55590  }
55591  if (has_configurable) {
55592  if (is_configurable) {
55593  new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
55594  } else {
55595  new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
55596  }
55597  }
55598  if (has_writable) {
55599  if (is_writable) {
55600  new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
55601  } else {
55602  new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
55603  }
55604  }
55605 
55606  /* XXX: write protect after flag? -> any chance of handling it here? */
55607 
55608  DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
55609  (unsigned long) new_flags));
55610 
55611  /*
55612  * Check whether we need to abandon an array part (if it exists)
55613  */
55614 
55615  if (curr.a_idx >= 0) {
55616  duk_bool_t rc;
55617 
55618  DUK_ASSERT(curr.e_idx < 0);
55619 
55620  if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
55621  duk_tval *tv1, *tv2;
55622 
55623  DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
55624 
55625  DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC); /* must have been, since in array part */
55626  DUK_ASSERT(!has_set);
55627  DUK_ASSERT(!has_get);
55628  DUK_ASSERT(idx_value >= 0); /* must be: if attributes match and we get here the value must differ (otherwise no change) */
55629 
55630  tv2 = duk_require_tval(ctx, idx_value);
55631  tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
55632  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate a_idx */
55633  goto success_exotics;
55634  }
55635 
55636  DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
55637  duk__abandon_array_checked(thr, obj);
55638  duk_pop(ctx); /* remove old value */
55639  rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
55640  DUK_UNREF(rc);
55641  DUK_ASSERT(rc != 0);
55642  DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
55643  }
55644 
55645  DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
55646 
55647  /* Array case is handled comprehensively above: either in entry
55648  * part or a virtual property.
55649  */
55650  DUK_ASSERT(curr.a_idx < 0);
55651 
55652  DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
55653  if (curr.e_idx >= 0) {
55654  DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
55655  } else {
55656  /* For Array .length the only allowed transition is for .length
55657  * to become non-writable.
55658  */
55659  if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
55660  duk_harray *a;
55661  a = (duk_harray *) obj;
55662  DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
55663  DUK_ASSERT_HARRAY_VALID(a);
55664  if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
55665  DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
55666  goto fail_virtual;
55667  }
55668  if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
55669  DUK_HARRAY_SET_LENGTH_WRITABLE(a);
55670  } else {
55671  DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
55672  }
55673  }
55674  }
55675 
55676  if (has_set) {
55677  duk_hobject *tmp;
55678 
55679  /* Virtual properties are non-configurable but with a 'force'
55680  * flag we might come here so check explicitly for virtual.
55681  */
55682  if (curr.e_idx < 0) {
55683  goto fail_virtual;
55684  }
55685 
55686  DUK_DDD(DUK_DDDPRINT("update existing property setter"));
55687  DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
55688 
55689  tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
55690  DUK_UNREF(tmp);
55691  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
55692  DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
55693  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
55694  }
55695  if (has_get) {
55696  duk_hobject *tmp;
55697 
55698  if (curr.e_idx < 0) {
55699  goto fail_virtual;
55700  }
55701 
55702  DUK_DDD(DUK_DDDPRINT("update existing property getter"));
55703  DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
55704 
55705  tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
55706  DUK_UNREF(tmp);
55707  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
55708  DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
55709  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp); /* side effects; may invalidate e_idx */
55710  }
55711  if (has_value) {
55712  duk_tval *tv1, *tv2;
55713 
55714  DUK_DDD(DUK_DDDPRINT("update existing property value"));
55715 
55716  if (curr.e_idx >= 0) {
55717  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
55718  tv2 = duk_require_tval(ctx, idx_value);
55719  tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
55720  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects; may invalidate e_idx */
55721  } else {
55722  DUK_ASSERT(curr.a_idx < 0); /* array part case handled comprehensively previously */
55723 
55724  DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
55725  /* XXX: Uint8Array and other typed array virtual writes not currently
55726  * handled.
55727  */
55728  if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
55729  duk_harray *a;
55730  a = (duk_harray *) obj;
55731  DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
55732  DUK_ASSERT_HARRAY_VALID(a);
55733  a->length = arrlen_new_len;
55734  } else {
55735  goto fail_virtual; /* should not happen */
55736  }
55737  }
55738  }
55739 
55740  /*
55741  * Standard algorithm succeeded without errors, check for exotic post-behaviors.
55742  *
55743  * Arguments exotic behavior in E5 Section 10.6 occurs after the standard
55744  * [[DefineOwnProperty]] has completed successfully.
55745  *
55746  * Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
55747  * prior to the default [[DefineOwnProperty]], but:
55748  * - for an array index key (e.g. "10") the final 'length' update occurs here
55749  * - for 'length' key the element deletion and 'length' update occurs here
55750  */
55751 
55752  success_exotics:
55753 
55754  /* curr.a_idx or curr.e_idx may have been invalidated by side effects
55755  * above.
55756  */
55757 
55758  /* [obj key desc value get set curr_value] */
55759 
55760  if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
55761  duk_harray *a;
55762 
55763  a = (duk_harray *) obj;
55764  DUK_ASSERT_HARRAY_VALID(a);
55765 
55766  if (arridx_new_array_length > 0) {
55767  /*
55768  * Note: zero works as a "no update" marker because the new length
55769  * can never be zero after a new property is written.
55770  */
55771 
55772  /* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
55773 
55774  DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
55775  (long) arridx_new_array_length));
55776 
55777  a->length = arridx_new_array_length;
55778  }
55779 
55780  if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
55781  /*
55782  * E5 Section 15.4.5.1, steps 3.k - 3.n. The order at the end combines
55783  * the error case 3.l.iii and the success case 3.m-3.n.
55784  */
55785 
55786  /* XXX: investigate whether write protect can be handled above, if we
55787  * just update length here while ignoring its protected status
55788  */
55789 
55790  duk_uint32_t result_len;
55791  duk_bool_t rc;
55792 
55793  DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
55794  "doing array element deletion and length update"));
55795 
55796  rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
55797 
55798  /* update length (curr points to length, and we assume it's still valid) */
55799  DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
55800 
55801  a->length = result_len;
55802 
55803  if (pending_write_protect) {
55804  DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
55805  DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
55806  }
55807 
55808  /* XXX: shrink array allocation or entries compaction here? */
55809  if (!rc) {
55810  DUK_DD(DUK_DDPRINT("array length write only partially successful"));
55811  goto fail_not_configurable;
55812  }
55813  }
55814  } else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
55815  duk_hobject *map;
55816  duk_hobject *varenv;
55817 
55818  DUK_ASSERT(arridx_new_array_length == 0);
55819  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)); /* traits are separate; in particular, arguments not an array */
55820 
55821  map = NULL;
55822  varenv = NULL;
55823  if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
55824  goto success_no_exotics;
55825  }
55826  DUK_ASSERT(map != NULL);
55827  DUK_ASSERT(varenv != NULL);
55828 
55829  /* [obj key desc value get set curr_value varname] */
55830 
55831  if (has_set || has_get) {
55832  /* = IsAccessorDescriptor(Desc) */
55833  DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
55834  "changed to an accessor, delete arguments binding"));
55835 
55836  (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
55837  } else {
55838  /* Note: this order matters (final value before deleting map entry must be done) */
55839  DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
55840  "check for value update / binding deletion"));
55841 
55842  if (has_value) {
55843  duk_hstring *varname;
55844 
55845  DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
55846  "update bound value (variable/argument)"));
55847 
55848  varname = duk_require_hstring(ctx, -1);
55849  DUK_ASSERT(varname != NULL);
55850 
55851  DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
55852  "key=%!O, varname=%!O, value=%!T",
55853  (duk_heaphdr *) key,
55854  (duk_heaphdr *) varname,
55855  (duk_tval *) duk_require_tval(ctx, idx_value)));
55856 
55857  /* strict flag for putvar comes from our caller (currently: fixed) */
55858  duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(ctx, idx_value), 1 /*throw_flag*/);
55859  }
55860  if (has_writable && !is_writable) {
55861  DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
55862  "changed to non-writable, delete arguments binding"));
55863 
55864  (void) duk_hobject_delprop_raw(thr, map, key, 0); /* ignore result */
55865  }
55866  }
55867 
55868  /* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
55869  * but this doesn't matter now.
55870  */
55871  }
55872 
55873  success_no_exotics:
55874  /* Some code paths use NORZ macros for simplicity, ensure refzero
55875  * handling is completed.
55876  */
55877  DUK_REFZERO_CHECK_SLOW(thr);
55878  return 1;
55879 
55880  fail_not_extensible:
55881  if (throw_flag) {
55882  DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
55883  }
55884  return 0;
55885 
55886  fail_virtual: /* just use the same "not configurable" error message" */
55887  fail_not_configurable:
55888  if (throw_flag) {
55889  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
55890  }
55891  return 0;
55892 }
55893 
55894 /*
55895  * Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
55896  */
55897 
55898 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_context *ctx, duk_small_uint_t required_desc_flags) {
55899  duk_hthread *thr = (duk_hthread *) ctx;
55900  duk_hstring *h_v;
55901  duk_hobject *h_obj;
55902  duk_propdesc desc;
55903  duk_bool_t ret;
55904 
55905  /* coercion order matters */
55906  h_v = duk_to_hstring_acceptsymbol(ctx, 0);
55907  DUK_ASSERT(h_v != NULL);
55908 
55909  h_obj = duk_push_this_coercible_to_object(ctx);
55910  DUK_ASSERT(h_obj != NULL);
55911 
55912  ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/); /* don't push value */
55913 
55914  duk_push_boolean(ctx, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
55915  return 1;
55916 }
55917 
55918 /*
55919  * Object.seal() and Object.freeze() (E5 Sections 15.2.3.8 and 15.2.3.9)
55920  *
55921  * Since the algorithms are similar, a helper provides both functions.
55922  * Freezing is essentially sealing + making plain properties non-writable.
55923  *
55924  * Note: virtual (non-concrete) properties which are non-configurable but
55925  * writable would pose some problems, but such properties do not currently
55926  * exist (all virtual properties are non-configurable and non-writable).
55927  * If they did exist, the non-configurability does NOT prevent them from
55928  * becoming non-writable. However, this change should be recorded somehow
55929  * so that it would turn up (e.g. when getting the property descriptor),
55930  * requiring some additional flags in the object.
55931  */
55932 
55933 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
55934  duk_uint_fast32_t i;
55935 
55936  DUK_ASSERT(thr != NULL);
55937  DUK_ASSERT(thr->heap != NULL);
55938  DUK_ASSERT(obj != NULL);
55939 
55940  DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55941 
55942 #if defined(DUK_USE_ROM_OBJECTS)
55943  if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55944  DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
55945  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
55946  }
55947 #endif
55948 
55949  /*
55950  * Abandon array part because all properties must become non-configurable.
55951  * Note that this is now done regardless of whether this is always the case
55952  * (skips check, but performance problem if caller would do this many times
55953  * for the same object; not likely).
55954  */
55955 
55956  duk__abandon_array_checked(thr, obj);
55957  DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
55958 
55959  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55960  duk_uint8_t *fp;
55961 
55962  /* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
55963  DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
55964 
55965  /* avoid multiple computations of flags address; bypasses macros */
55966  fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
55967  if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
55968  *fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
55969  } else {
55970  *fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
55971  }
55972  }
55973 
55974  DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
55975 
55976  /* no need to compact since we already did that in duk__abandon_array_checked()
55977  * (regardless of whether an array part existed or not.
55978  */
55979 
55980  return;
55981 }
55982 
55983 /*
55984  * Object.isSealed() and Object.isFrozen() (E5 Sections 15.2.3.11, 15.2.3.13)
55985  *
55986  * Since the algorithms are similar, a helper provides both functions.
55987  * Freezing is essentially sealing + making plain properties non-writable.
55988  *
55989  * Note: all virtual (non-concrete) properties are currently non-configurable
55990  * and non-writable (and there are no accessor virtual properties), so they don't
55991  * need to be considered here now.
55992  */
55993 
55994 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
55995  duk_uint_fast32_t i;
55996 
55997  DUK_ASSERT(obj != NULL);
55998  DUK_UNREF(thr);
55999 
56000  /* Note: no allocation pressure, no need to check refcounts etc */
56001 
56002  /* must not be extensible */
56003  if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
56004  return 0;
56005  }
56006 
56007  /* all virtual properties are non-configurable and non-writable */
56008 
56009  /* entry part must not contain any configurable properties, or
56010  * writable properties (if is_frozen).
56011  */
56012  for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
56013  duk_small_uint_t flags;
56014 
56015  if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
56016  continue;
56017  }
56018 
56019  /* avoid multiple computations of flags address; bypasses macros */
56020  flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
56021 
56022  if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
56023  return 0;
56024  }
56025  if (is_frozen &&
56026  !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
56027  (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
56028  return 0;
56029  }
56030  }
56031 
56032  /* array part must not contain any non-unused properties, as they would
56033  * be configurable and writable.
56034  */
56035  for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
56036  duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
56037  if (!DUK_TVAL_IS_UNUSED(tv)) {
56038  return 0;
56039  }
56040  }
56041 
56042  return 1;
56043 }
56044 
56045 /*
56046  * Object.preventExtensions() and Object.isExtensible() (E5 Sections 15.2.3.10, 15.2.3.13)
56047  *
56048  * Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
56049  * and the Object built-in bindings.
56050  */
56051 
56052 /* automatic undefs */
56053 #undef DUK__HASH_DELETED
56054 #undef DUK__HASH_INITIAL
56055 #undef DUK__HASH_PROBE_STEP
56056 #undef DUK__HASH_UNUSED
56057 #undef DUK__NO_ARRAY_INDEX
56058 #undef DUK__VALSTACK_PROXY_LOOKUP
56059 #undef DUK__VALSTACK_SPACE
56060 /*
56061  * Misc support functions
56062  */
56063 
56064 /* #include duk_internal.h -> already included */
56065 
56066 DUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware) {
56067  duk_uint32_t boff;
56068  const duk_uint8_t *p, *p_start, *p_end;
56069  duk_ucodepoint_t cp1;
56070  duk_ucodepoint_t cp2;
56071 
56072  /* Caller must check character offset to be inside the string. */
56073  DUK_ASSERT(thr != NULL);
56074  DUK_ASSERT(h != NULL);
56075  DUK_ASSERT_DISABLE(pos >= 0); /* unsigned */
56076  DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
56077 
56078  boff = duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
56079  DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
56080  (long) pos, (long) boff, (duk_heaphdr *) h));
56081  DUK_ASSERT_DISABLE(boff >= 0);
56082  DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
56083 
56084  p_start = DUK_HSTRING_GET_DATA(h);
56085  p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
56086  p = p_start + boff;
56087  DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
56088  (const void *) p_start, (const void *) p_end,
56089  (const void *) p));
56090 
56091  /* For invalid UTF-8 (never happens for standard Ecmascript strings)
56092  * return U+FFFD replacement character.
56093  */
56094  if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
56095  if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
56096  /* The decode helper is memory safe even if 'cp1' was
56097  * decoded at the end of the string and 'p' is no longer
56098  * within string memory range.
56099  */
56100  cp2 = 0; /* If call fails, this is left untouched and won't match cp2 check. */
56101  (void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
56102  if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
56103  cp1 = ((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL;
56104  }
56105  }
56106  } else {
56107  cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
56108  }
56109 
56110  return cp1;
56111 }
56112 
56113 #if !defined(DUK_USE_HSTRING_CLEN)
56114 DUK_INTERNAL duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
56115  if (DUK_HSTRING_HAS_ASCII(h)) {
56116  /* Most practical strings will go here. */
56117  return DUK_HSTRING_GET_BYTELEN(h);
56118  } else {
56119  return duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
56120  }
56121 }
56122 #endif /* !DUK_USE_HSTRING_CLEN */
56123 /*
56124  * duk_hthread allocation and freeing.
56125  */
56126 
56127 /* #include duk_internal.h -> already included */
56128 
56129 /*
56130  * Allocate initial stacks for a thread. Note that 'thr' must be reachable
56131  * as a garbage collection may be triggered by the allocation attempts.
56132  * Returns zero (without leaking memory) if init fails.
56133  */
56134 
56135 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
56136  duk_size_t alloc_size;
56137  duk_size_t i;
56138 
56139  DUK_ASSERT(heap != NULL);
56140  DUK_ASSERT(thr != NULL);
56141  DUK_ASSERT(thr->valstack == NULL);
56142  DUK_ASSERT(thr->valstack_end == NULL);
56143  DUK_ASSERT(thr->valstack_bottom == NULL);
56144  DUK_ASSERT(thr->valstack_top == NULL);
56145  DUK_ASSERT(thr->callstack == NULL);
56146  DUK_ASSERT(thr->catchstack == NULL);
56147 
56148  /* valstack */
56149  alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
56150  thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
56151  if (!thr->valstack) {
56152  goto fail;
56153  }
56154  DUK_MEMZERO(thr->valstack, alloc_size);
56155  thr->valstack_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
56156 #if !defined(DUK_USE_PREFER_SIZE)
56157  thr->valstack_size = DUK_VALSTACK_INITIAL_SIZE;
56158 #endif
56159  thr->valstack_bottom = thr->valstack;
56160  thr->valstack_top = thr->valstack;
56161 
56162  for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
56163  DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
56164  }
56165 
56166  /* callstack */
56167  alloc_size = sizeof(duk_activation) * DUK_CALLSTACK_INITIAL_SIZE;
56168  thr->callstack = (duk_activation *) DUK_ALLOC(heap, alloc_size);
56169  if (!thr->callstack) {
56170  goto fail;
56171  }
56172  DUK_MEMZERO(thr->callstack, alloc_size);
56173  thr->callstack_size = DUK_CALLSTACK_INITIAL_SIZE;
56174  DUK_ASSERT(thr->callstack_top == 0);
56175 
56176  /* catchstack */
56177  alloc_size = sizeof(duk_catcher) * DUK_CATCHSTACK_INITIAL_SIZE;
56178  thr->catchstack = (duk_catcher *) DUK_ALLOC(heap, alloc_size);
56179  if (!thr->catchstack) {
56180  goto fail;
56181  }
56182  DUK_MEMZERO(thr->catchstack, alloc_size);
56183  thr->catchstack_size = DUK_CATCHSTACK_INITIAL_SIZE;
56184  DUK_ASSERT(thr->catchstack_top == 0);
56185 
56186  return 1;
56187 
56188  fail:
56189  DUK_FREE(heap, thr->valstack);
56190  DUK_FREE(heap, thr->callstack);
56191  DUK_FREE(heap, thr->catchstack);
56192 
56193  thr->valstack = NULL;
56194  thr->callstack = NULL;
56195  thr->catchstack = NULL;
56196  return 0;
56197 }
56198 
56199 /* For indirect allocs. */
56200 
56201 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
56202  duk_hthread *thr = (duk_hthread *) ud;
56203  DUK_UNREF(heap);
56204  return (void *) thr->valstack;
56205 }
56206 
56207 DUK_INTERNAL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud) {
56208  duk_hthread *thr = (duk_hthread *) ud;
56209  DUK_UNREF(heap);
56210  return (void *) thr->callstack;
56211 }
56212 
56213 DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) {
56214  duk_hthread *thr = (duk_hthread *) ud;
56215  DUK_UNREF(heap);
56216  return (void *) thr->catchstack;
56217 }
56218 /*
56219  * Initialize built-in objects. Current thread must have a valstack
56220  * and initialization errors may longjmp, so a setjmp() catch point
56221  * must exist.
56222  */
56223 
56224 /* #include duk_internal.h -> already included */
56225 
56226 /*
56227  * Encoding constants, must match genbuiltins.py
56228  */
56229 
56230 #define DUK__PROP_FLAGS_BITS 3
56231 #define DUK__LENGTH_PROP_BITS 3
56232 #define DUK__NARGS_BITS 3
56233 #define DUK__PROP_TYPE_BITS 3
56234 
56235 #define DUK__NARGS_VARARGS_MARKER 0x07
56236 
56237 #define DUK__PROP_TYPE_DOUBLE 0
56238 #define DUK__PROP_TYPE_STRING 1
56239 #define DUK__PROP_TYPE_STRIDX 2
56240 #define DUK__PROP_TYPE_BUILTIN 3
56241 #define DUK__PROP_TYPE_UNDEFINED 4
56242 #define DUK__PROP_TYPE_BOOLEAN_TRUE 5
56243 #define DUK__PROP_TYPE_BOOLEAN_FALSE 6
56244 #define DUK__PROP_TYPE_ACCESSOR 7
56245 
56246 /*
56247  * Create built-in objects by parsing an init bitstream generated
56248  * by genbuiltins.py.
56249  */
56250 
56251 #if defined(DUK_USE_ROM_OBJECTS)
56252 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
56253 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
56254  duk_context *ctx;
56255  duk_hobject *h1;
56256 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
56257  duk_hobject *h2;
56258  duk_uint8_t *props;
56259  duk_size_t alloc_size;
56260 #endif
56261 
56262  ctx = (duk_context *) thr;
56263 
56264  /* XXX: refactor into internal helper, duk_clone_hobject() */
56265 
56266 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
56267  /* Inherit from ROM-based global object: less RAM usage, less transparent. */
56268  h1 = duk_push_object_helper(ctx,
56269  DUK_HOBJECT_FLAG_EXTENSIBLE |
56270  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
56271  DUK_BIDX_GLOBAL);
56272  DUK_ASSERT(h1 != NULL);
56273 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
56274  /* Clone the properties of the ROM-based global object to create a
56275  * fully RAM-based global object. Uses more memory than the inherit
56276  * model but more compliant.
56277  */
56278  h1 = duk_push_object_helper(ctx,
56279  DUK_HOBJECT_FLAG_EXTENSIBLE |
56280  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
56281  DUK_BIDX_OBJECT_PROTOTYPE);
56282  DUK_ASSERT(h1 != NULL);
56283  h2 = thr->builtins[DUK_BIDX_GLOBAL];
56284  DUK_ASSERT(h2 != NULL);
56285 
56286  /* Copy the property table verbatim; this handles attributes etc.
56287  * For ROM objects it's not necessary (or possible) to update
56288  * refcounts so leave them as is.
56289  */
56290  alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h2);
56291  DUK_ASSERT(alloc_size > 0);
56292  props = DUK_ALLOC(thr->heap, alloc_size);
56293  if (!props) {
56294  DUK_ERROR_ALLOC_FAILED(thr);
56295  return;
56296  }
56297  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h2) != NULL);
56298  DUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h2), alloc_size);
56299 
56300  /* XXX: keep property attributes or tweak them here?
56301  * Properties will now be non-configurable even when they're
56302  * normally configurable for the global object.
56303  */
56304 
56305  DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h1) == NULL);
56306  DUK_HOBJECT_SET_PROPS(thr->heap, h1, props);
56307  DUK_HOBJECT_SET_ESIZE(h1, DUK_HOBJECT_GET_ESIZE(h2));
56308  DUK_HOBJECT_SET_ENEXT(h1, DUK_HOBJECT_GET_ENEXT(h2));
56309  DUK_HOBJECT_SET_ASIZE(h1, DUK_HOBJECT_GET_ASIZE(h2));
56310  DUK_HOBJECT_SET_HSIZE(h1, DUK_HOBJECT_GET_HSIZE(h2));
56311 #else
56312 #error internal error in defines
56313 #endif
56314 
56315  duk_hobject_compact_props(thr, h1);
56316  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
56317  DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL])); /* no need to decref */
56318  thr->builtins[DUK_BIDX_GLOBAL] = h1;
56319  DUK_HOBJECT_INCREF(thr, h1);
56320  DUK_D(DUK_DPRINT("duplicated global object: %!O", h1));
56321 
56322 
56323  /* Create a fresh object environment for the global scope. This is
56324  * needed so that the global scope points to the newly created RAM-based
56325  * global object.
56326  */
56327  h1 = duk_push_object_helper(ctx,
56328  DUK_HOBJECT_FLAG_EXTENSIBLE |
56329  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
56330  -1); /* no prototype */
56331  DUK_ASSERT(h1 != NULL);
56332  duk_dup_m2(ctx);
56333  duk_dup_top(ctx); /* -> [ ... new_global new_globalenv new_global new_global ] */
56334  duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
56335  duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
56336 
56337  duk_hobject_compact_props(thr, h1);
56338  DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
56339  DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV])); /* no need to decref */
56340  thr->builtins[DUK_BIDX_GLOBAL_ENV] = h1;
56341  DUK_HOBJECT_INCREF(thr, h1);
56342  DUK_D(DUK_DPRINT("duplicated global env: %!O", h1));
56343 
56344  duk_pop_2(ctx);
56345 }
56346 #endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
56347 
56348 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
56349  /* Setup builtins from ROM objects. All heaps/threads will share
56350  * the same readonly objects.
56351  */
56352  duk_small_uint_t i;
56353 
56354  for (i = 0; i < DUK_NUM_BUILTINS; i++) {
56355  duk_hobject *h;
56356  h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
56357  DUK_ASSERT(h != NULL);
56358  thr->builtins[i] = h;
56359  }
56360 
56361 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
56362  /* By default the global object is read-only which is often much
56363  * more of an issue than having read-only built-in objects (like
56364  * RegExp, Date, etc). Use a RAM-based copy of the global object
56365  * and the global environment object for convenience.
56366  */
56367  duk__duplicate_ram_global_object(thr);
56368 #endif
56369 }
56370 #else /* DUK_USE_ROM_OBJECTS */
56371 DUK_LOCAL void duk__push_stridx(duk_context *ctx, duk_bitdecoder_ctx *bd) {
56372  duk_small_uint_t n;
56373 
56374  n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56375  DUK_ASSERT_DISABLE(n >= 0); /* unsigned */
56376  DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
56377  duk_push_hstring_stridx(ctx, n);
56378 }
56379 DUK_LOCAL void duk__push_string(duk_context *ctx, duk_bitdecoder_ctx *bd) {
56380  /* XXX: built-ins data could provide a maximum length that is
56381  * actually needed; bitpacked max length is now 256 bytes.
56382  */
56383  duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
56384  duk_small_uint_t len;
56385 
56386  len = duk_bd_decode_bitpacked_string(bd, tmp);
56387  duk_push_lstring(ctx, (const char *) tmp, (duk_size_t) len);
56388 }
56389 DUK_LOCAL void duk__push_stridx_or_string(duk_context *ctx, duk_bitdecoder_ctx *bd) {
56390  duk_small_uint_t n;
56391 
56392  n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56393  if (n == 0) {
56394  duk__push_string(ctx, bd);
56395  } else {
56396  n--;
56397  DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
56398  duk_push_hstring_stridx(ctx, n);
56399  }
56400 }
56401 DUK_LOCAL void duk__push_double(duk_context *ctx, duk_bitdecoder_ctx *bd) {
56402  duk_double_union du;
56403  duk_small_uint_t i;
56404 
56405  for (i = 0; i < 8; i++) {
56406  /* Encoding endianness must match target memory layout,
56407  * build scripts and genbuiltins.py must ensure this.
56408  */
56409  du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
56410  }
56411 
56412  duk_push_number(ctx, du.d); /* push operation normalizes NaNs */
56413 }
56414 
56415 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
56416  duk_context *ctx = (duk_context *) thr;
56417  duk_bitdecoder_ctx bd_ctx;
56418  duk_bitdecoder_ctx *bd = &bd_ctx; /* convenience */
56419  duk_hobject *h;
56420  duk_small_uint_t i, j;
56421 
56422  DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
56423 
56424  DUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));
56425  bd->data = (const duk_uint8_t *) duk_builtins_data;
56426  bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
56427 
56428  /*
56429  * First create all built-in bare objects on the empty valstack.
56430  *
56431  * Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
56432  * stack indices matching their eventual thr->builtins[] index.
56433  *
56434  * Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
56435  * will exist on the value stack during init but won't be placed
56436  * into thr->builtins[]. These are objects referenced in some way
56437  * from thr->builtins[] roots but which don't need to be indexed by
56438  * Duktape through thr->builtins[] (e.g. user custom objects).
56439  */
56440 
56441  duk_require_stack(ctx, DUK_NUM_ALL_BUILTINS);
56442 
56443  DUK_DD(DUK_DDPRINT("create empty built-ins"));
56444  DUK_ASSERT_TOP(ctx, 0);
56445  for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
56446  duk_small_uint_t class_num;
56447  duk_small_int_t len = -1; /* must be signed */
56448 
56449  class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56450  len = (duk_small_int_t) duk_bd_decode_flagged(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
56451 
56452  if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
56453  duk_small_uint_t natidx;
56454  duk_int_t c_nargs; /* must hold DUK_VARARGS */
56455  duk_c_function c_func;
56456  duk_int16_t magic;
56457 
56458  DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
56459  DUK_ASSERT(len >= 0);
56460 
56461  natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56462  DUK_ASSERT(natidx != 0);
56463  c_func = duk_bi_native_functions[natidx];
56464  DUK_ASSERT(c_func != NULL);
56465 
56466  c_nargs = (duk_small_uint_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, len /*def_value*/);
56467  if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
56468  c_nargs = DUK_VARARGS;
56469  }
56470 
56471  /* XXX: set magic directly here? (it could share the c_nargs arg) */
56472  duk_push_c_function_noexotic(ctx, c_func, c_nargs);
56473 
56474  h = duk_known_hobject(ctx, -1);
56475 
56476  /* Currently all built-in native functions are strict.
56477  * duk_push_c_function() now sets strict flag, so
56478  * assert for it.
56479  */
56480  DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
56481 
56482  /* XXX: function properties */
56483 
56484  duk__push_stridx_or_string(ctx, bd);
56485 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
56486  duk_xdef_prop_stridx_short(ctx,
56487  -2,
56488  DUK_STRIDX_NAME,
56489  DUK_PROPDESC_FLAGS_C);
56490 #else
56491  duk_pop(ctx); /* Not very ideal but good enough for now. */
56492 #endif
56493 
56494  /* Almost all global level Function objects are constructable
56495  * but not all: Function.prototype is a non-constructable,
56496  * callable Function.
56497  */
56498  if (duk_bd_decode_flag(bd)) {
56499  DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
56500  } else {
56501  DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
56502  }
56503 
56504  /* Cast converts magic to 16-bit signed value */
56505  magic = (duk_int16_t) duk_bd_decode_varuint(bd);
56506  ((duk_hnatfunc *) h)->magic = magic;
56507  } else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
56508  duk_push_array(ctx);
56509  } else {
56510  (void) duk_push_object_helper(ctx,
56511  DUK_HOBJECT_FLAG_EXTENSIBLE,
56512  -1); /* no prototype or class yet */
56513 
56514  }
56515 
56516  h = duk_known_hobject(ctx, -1);
56517  DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
56518 
56519  if (i < DUK_NUM_BUILTINS) {
56520  thr->builtins[i] = h;
56521  DUK_HOBJECT_INCREF(thr, &h->hdr);
56522  }
56523 
56524  if (len >= 0) {
56525  /* In ES2015+ built-in function object .length property
56526  * has property attributes C (configurable only):
56527  * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
56528  *
56529  * Array.prototype remains an Array instance in ES2015+
56530  * and its length has attributes W (writable only).
56531  * Because .length is now virtual for duk_harray, it is
56532  * not encoded explicitly in init data.
56533  */
56534 
56535  DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY); /* .length is virtual */
56536  duk_push_int(ctx, len);
56537  duk_xdef_prop_stridx_short(ctx,
56538  -2,
56539  DUK_STRIDX_LENGTH,
56540  DUK_PROPDESC_FLAGS_C);
56541  }
56542 
56543  /* enable exotic behaviors last */
56544 
56545  if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
56546  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)); /* set by duk_push_array() */
56547  }
56548  if (class_num == DUK_HOBJECT_CLASS_STRING) {
56549  DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
56550  }
56551 
56552  /* some assertions */
56553 
56554  DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
56555  /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
56556  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
56557  DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
56558  /* DUK_HOBJECT_FLAG_NATFUNC varies */
56559  DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h));
56560  DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
56561  /* DUK_HOBJECT_FLAG_STRICT varies */
56562  DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) || /* all native functions have NEWENV */
56563  DUK_HOBJECT_HAS_NEWENV(h));
56564  DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
56565  DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
56566  DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h));
56567  /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
56568  /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
56569  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
56570 
56571  DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
56572  }
56573 
56574  /*
56575  * Then decode the builtins init data (see genbuiltins.py) to
56576  * init objects
56577  */
56578 
56579  DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
56580  for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
56581  duk_small_uint_t t;
56582  duk_small_uint_t num;
56583 
56584  DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
56585  h = duk_known_hobject(ctx, i);
56586 
56587  t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56588  if (t > 0) {
56589  t--;
56590  DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
56591  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(ctx, t));
56592  }
56593 
56594  t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56595  if (t > 0) {
56596  /* 'prototype' property for all built-in objects (which have it) has attributes:
56597  * [[Writable]] = false,
56598  * [[Enumerable]] = false,
56599  * [[Configurable]] = false
56600  */
56601  t--;
56602  DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
56603  duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_PROTOTYPE, t, DUK_PROPDESC_FLAGS_NONE);
56604  }
56605 
56606  t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56607  if (t > 0) {
56608  /* 'constructor' property for all built-in objects (which have it) has attributes:
56609  * [[Writable]] = true,
56610  * [[Enumerable]] = false,
56611  * [[Configurable]] = true
56612  */
56613  t--;
56614  DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
56615  duk_xdef_prop_stridx_builtin(ctx, i, DUK_STRIDX_CONSTRUCTOR, t, DUK_PROPDESC_FLAGS_WC);
56616  }
56617 
56618  /* normal valued properties */
56619  num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56620  DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
56621  for (j = 0; j < num; j++) {
56622  duk_small_uint_t defprop_flags;
56623 
56624  duk__push_stridx_or_string(ctx, bd);
56625 
56626  /*
56627  * Property attribute defaults are defined in E5 Section 15 (first
56628  * few pages); there is a default for all properties and a special
56629  * default for 'length' properties. Variation from the defaults is
56630  * signaled using a single flag bit in the bitstream.
56631  */
56632 
56633  if (duk_bd_decode_flag(bd)) {
56634  defprop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);
56635  } else {
56636  defprop_flags = DUK_PROPDESC_FLAGS_WC;
56637  }
56638  defprop_flags |= DUK_DEFPROP_FORCE |
56639  DUK_DEFPROP_HAVE_VALUE |
56640  DUK_DEFPROP_HAVE_WRITABLE |
56641  DUK_DEFPROP_HAVE_ENUMERABLE |
56642  DUK_DEFPROP_HAVE_CONFIGURABLE; /* Defaults for data properties. */
56643 
56644  /* The writable, enumerable, configurable flags in prop_flags
56645  * match both duk_def_prop() and internal property flags.
56646  */
56647  DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
56648  DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
56649  DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
56650 
56651  t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
56652 
56653  DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
56654  (long) i, (long) j, duk_get_tval(ctx, -1), (unsigned long) defprop_flags, (long) t));
56655 
56656  switch (t) {
56657  case DUK__PROP_TYPE_DOUBLE: {
56658  duk__push_double(ctx, bd);
56659  break;
56660  }
56661  case DUK__PROP_TYPE_STRING: {
56662  duk__push_string(ctx, bd);
56663  break;
56664  }
56665  case DUK__PROP_TYPE_STRIDX: {
56666  duk__push_stridx(ctx, bd);
56667  break;
56668  }
56669  case DUK__PROP_TYPE_BUILTIN: {
56670  duk_small_uint_t bidx;
56671 
56672  bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56673  duk_dup(ctx, (duk_idx_t) bidx);
56674  break;
56675  }
56676  case DUK__PROP_TYPE_UNDEFINED: {
56677  duk_push_undefined(ctx);
56678  break;
56679  }
56680  case DUK__PROP_TYPE_BOOLEAN_TRUE: {
56681  duk_push_true(ctx);
56682  break;
56683  }
56684  case DUK__PROP_TYPE_BOOLEAN_FALSE: {
56685  duk_push_false(ctx);
56686  break;
56687  }
56688  case DUK__PROP_TYPE_ACCESSOR: {
56689  duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56690  duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56691  duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56692  duk_c_function c_func_getter;
56693  duk_c_function c_func_setter;
56694 
56695  DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
56696  (long) i, duk_get_tval(ctx, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
56697 
56698  c_func_getter = duk_bi_native_functions[natidx_getter];
56699  if (c_func_getter != NULL) {
56700  duk_push_c_function_noconstruct_noexotic(ctx, c_func_getter, 0); /* always 0 args */
56701  duk_set_magic(ctx, -1, (duk_int_t) accessor_magic);
56702  defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
56703  }
56704  c_func_setter = duk_bi_native_functions[natidx_setter];
56705  if (c_func_setter != NULL) {
56706  duk_push_c_function_noconstruct_noexotic(ctx, c_func_setter, 1); /* always 1 arg */
56707  duk_set_magic(ctx, -1, (duk_int_t) accessor_magic);
56708  defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
56709  }
56710 
56711  /* Writable flag doesn't make sense for an accessor. */
56712  DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0); /* genbuiltins.py ensures */
56713 
56714  defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
56715  defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
56716  break;
56717  }
56718  default: {
56719  /* exhaustive */
56720  DUK_UNREACHABLE();
56721  }
56722  }
56723 
56724  duk_def_prop(ctx, i, defprop_flags);
56725  DUK_ASSERT_TOP(ctx, DUK_NUM_ALL_BUILTINS);
56726  }
56727 
56728  /* native function properties */
56729  num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56730  DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
56731  for (j = 0; j < num; j++) {
56732  duk_hstring *h_key;
56733  duk_small_uint_t natidx;
56734  duk_int_t c_nargs; /* must hold DUK_VARARGS */
56735  duk_small_uint_t c_length;
56736  duk_int16_t magic;
56737  duk_c_function c_func;
56738  duk_hnatfunc *h_func;
56739 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
56740  duk_small_int_t lightfunc_eligible;
56741 #endif
56742 
56743  duk__push_stridx_or_string(ctx, bd);
56744  h_key = duk_known_hstring(ctx, -1);
56745  DUK_UNREF(h_key);
56746  natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
56747 
56748  c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
56749  c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_int32_t) c_length /*def_value*/);
56750  if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
56751  c_nargs = DUK_VARARGS;
56752  }
56753 
56754  c_func = duk_bi_native_functions[natidx];
56755 
56756  DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
56757  (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
56758  (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
56759 
56760  /* Cast converts magic to 16-bit signed value */
56761  magic = (duk_int16_t) duk_bd_decode_varuint(bd);
56762 
56763 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
56764  lightfunc_eligible =
56765  ((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
56766  (c_length <= DUK_LFUNC_LENGTH_MAX) &&
56767  (magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
56768 
56769  if (h_key == DUK_HTHREAD_STRING_EVAL(thr) ||
56770  h_key == DUK_HTHREAD_STRING_YIELD(thr) ||
56771  h_key == DUK_HTHREAD_STRING_RESUME(thr)) {
56772  /* These functions have trouble working as lightfuncs.
56773  * Some of them have specific asserts and some may have
56774  * additional properties (e.g. 'require.id' may be written).
56775  */
56776  DUK_D(DUK_DPRINT("reject as lightfunc: key=%!O, i=%d, j=%d", (duk_heaphdr *) h_key, (int) i, (int) j));
56777  lightfunc_eligible = 0;
56778  }
56779 
56780  if (lightfunc_eligible) {
56781  duk_tval tv_lfunc;
56782  duk_small_uint_t lf_nargs = (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
56783  duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
56784  DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
56785  duk_push_tval(ctx, &tv_lfunc);
56786  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)));
56787  goto lightfunc_skip;
56788  }
56789 
56790  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));
56791 #endif /* DUK_USE_LIGHTFUNC_BUILTINS */
56792 
56793  /* [ (builtin objects) name ] */
56794 
56795  duk_push_c_function_noconstruct_noexotic(ctx, c_func, c_nargs);
56796  h_func = duk_known_hnatfunc(ctx, -1);
56797  DUK_UNREF(h_func);
56798 
56799  /* Currently all built-in native functions are strict.
56800  * This doesn't matter for many functions, but e.g.
56801  * String.prototype.charAt (and other string functions)
56802  * rely on being strict so that their 'this' binding is
56803  * not automatically coerced.
56804  */
56805  DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
56806 
56807  /* No built-in functions are constructable except the top
56808  * level ones (Number, etc).
56809  */
56810  DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
56811 
56812  /* XXX: any way to avoid decoding magic bit; there are quite
56813  * many function properties and relatively few with magic values.
56814  */
56815  h_func->magic = magic;
56816 
56817  /* [ (builtin objects) name func ] */
56818 
56819  duk_push_int(ctx, c_length);
56820  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
56821 
56822  duk_dup_m2(ctx);
56823  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
56824 
56825  /* XXX: other properties of function instances; 'arguments', 'caller'. */
56826 
56827  DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
56828  (long) i, (long) j, (duk_tval *) duk_get_tval(ctx, -1)));
56829 
56830  /* [ (builtin objects) name func ] */
56831 
56832  /*
56833  * The default property attributes are correct for all
56834  * function valued properties of built-in objects now.
56835  */
56836 
56837 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
56838  lightfunc_skip:
56839 #endif
56840 
56841  duk_xdef_prop(ctx, i, DUK_PROPDESC_FLAGS_WC);
56842 
56843  /* [ (builtin objects) ] */
56844  }
56845  }
56846 
56847  /*
56848  * Special post-tweaks, for cases not covered by the init data format.
56849  *
56850  * - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
56851  * toGMTString is required to have the same Function object as
56852  * toUTCString in E5 Section B.2.6. Note that while Smjs respects
56853  * this, V8 does not (the Function objects are distinct).
56854  *
56855  * - Make DoubleError non-extensible.
56856  *
56857  * - Add info about most important effective compile options to Duktape.
56858  *
56859  * - Possibly remove some properties (values or methods) which are not
56860  * desirable with current feature options but are not currently
56861  * conditional in init data.
56862  */
56863 
56864 #if defined(DUK_USE_DATE_BUILTIN)
56865  duk_get_prop_stridx_short(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
56866  duk_xdef_prop_stridx_short(ctx, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
56867 #endif
56868 
56869  h = duk_known_hobject(ctx, DUK_BIDX_DOUBLE_ERROR);
56870  DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
56871 
56872 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
56873  DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
56874  (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
56875 #endif
56876 
56877 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
56878  DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
56879  (void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
56880 #endif
56881 
56882  /* XXX: relocate */
56883  duk_push_string(ctx,
56884  /* Endianness indicator */
56885 #if defined(DUK_USE_INTEGER_LE)
56886  "l"
56887 #elif defined(DUK_USE_INTEGER_BE)
56888  "b"
56889 #elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
56890  "m"
56891 #else
56892  "?"
56893 #endif
56894 #if defined(DUK_USE_DOUBLE_LE)
56895  "l"
56896 #elif defined(DUK_USE_DOUBLE_BE)
56897  "b"
56898 #elif defined(DUK_USE_DOUBLE_ME)
56899  "m"
56900 #else
56901  "?"
56902 #endif
56903  " "
56904  /* Packed or unpacked tval */
56905 #if defined(DUK_USE_PACKED_TVAL)
56906  "p"
56907 #else
56908  "u"
56909 #endif
56910 #if defined(DUK_USE_FASTINT)
56911  "f"
56912 #endif
56913  " "
56914  /* Low memory options */
56915 #if defined(DUK_USE_STRTAB_CHAIN)
56916  "c" /* chain */
56917 #elif defined(DUK_USE_STRTAB_PROBE)
56918  "p" /* probe */
56919 #else
56920  "?"
56921 #endif
56922 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
56923  "n"
56924 #endif
56925 #if defined(DUK_USE_HEAPPTR16)
56926  "h"
56927 #endif
56928 #if defined(DUK_USE_DATAPTR16)
56929  "d"
56930 #endif
56931 #if defined(DUK_USE_FUNCPTR16)
56932  "f"
56933 #endif
56934 #if defined(DUK_USE_REFCOUNT16)
56935  "R"
56936 #endif
56937 #if defined(DUK_USE_STRHASH16)
56938  "H"
56939 #endif
56940 #if defined(DUK_USE_STRLEN16)
56941  "S"
56942 #endif
56943 #if defined(DUK_USE_BUFLEN16)
56944  "B"
56945 #endif
56946 #if defined(DUK_USE_OBJSIZES16)
56947  "O"
56948 #endif
56949 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
56950  "L"
56951 #endif
56952 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
56953  /* XXX: This won't be shown in practice now
56954  * because this code is not run when builtins
56955  * are in ROM.
56956  */
56957  "Z"
56958 #endif
56959  " "
56960  /* Object property allocation layout */
56961 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
56962  "p1"
56963 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
56964  "p2"
56965 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
56966  "p3"
56967 #else
56968  "p?"
56969 #endif
56970  " "
56971  /* Alignment guarantee */
56972 #if (DUK_USE_ALIGN_BY == 4)
56973  "a4"
56974 #elif (DUK_USE_ALIGN_BY == 8)
56975  "a8"
56976 #elif (DUK_USE_ALIGN_BY == 1)
56977  "a1"
56978 #else
56979 #error invalid DUK_USE_ALIGN_BY
56980 #endif
56981  " "
56982  /* Architecture, OS, and compiler strings */
56983  DUK_USE_ARCH_STRING
56984  " "
56985  DUK_USE_OS_STRING
56986  " "
56987  DUK_USE_COMPILER_STRING);
56988  duk_xdef_prop_stridx_short(ctx, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
56989 
56990  /*
56991  * Since built-ins are not often extended, compact them.
56992  */
56993 
56994  DUK_DD(DUK_DDPRINT("compact built-ins"));
56995  for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
56996  duk_hobject_compact_props(thr, duk_known_hobject(ctx, i));
56997  }
56998 
56999  DUK_D(DUK_DPRINT("INITBUILTINS END"));
57000 
57001 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
57002  for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
57003  DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
57004  (long) i, (duk_heaphdr *) duk_require_hobject(ctx, i)));
57005  }
57006 #endif
57007 
57008  /*
57009  * Pop built-ins from stack: they are now INCREF'd and
57010  * reachable from the builtins[] array or indirectly
57011  * through builtins[].
57012  */
57013 
57014  duk_set_top(ctx, 0);
57015  DUK_ASSERT_TOP(ctx, 0);
57016 }
57017 #endif /* DUK_USE_ROM_OBJECTS */
57018 
57019 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
57020  duk_small_uint_t i;
57021 
57022  for (i = 0; i < DUK_NUM_BUILTINS; i++) {
57023  thr_to->builtins[i] = thr_from->builtins[i];
57024  DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]); /* side effect free */
57025  }
57026 }
57027 
57028 /* automatic undefs */
57029 #undef DUK__LENGTH_PROP_BITS
57030 #undef DUK__NARGS_BITS
57031 #undef DUK__NARGS_VARARGS_MARKER
57032 #undef DUK__PROP_FLAGS_BITS
57033 #undef DUK__PROP_TYPE_ACCESSOR
57034 #undef DUK__PROP_TYPE_BITS
57035 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
57036 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
57037 #undef DUK__PROP_TYPE_BUILTIN
57038 #undef DUK__PROP_TYPE_DOUBLE
57039 #undef DUK__PROP_TYPE_STRIDX
57040 #undef DUK__PROP_TYPE_STRING
57041 #undef DUK__PROP_TYPE_UNDEFINED
57042 /*
57043  * Thread support.
57044  */
57045 
57046 /* #include duk_internal.h -> already included */
57047 
57048 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
57049  DUK_ASSERT(thr != NULL);
57050 
57051  /* Order of unwinding is important */
57052 
57053  duk_hthread_catchstack_unwind(thr, 0);
57054 
57055  duk_hthread_callstack_unwind(thr, 0); /* side effects, possibly errors */
57056 
57057  thr->valstack_bottom = thr->valstack;
57058  duk_set_top((duk_context *) thr, 0); /* unwinds valstack, updating refcounts */
57059 
57060  thr->state = DUK_HTHREAD_STATE_TERMINATED;
57061 
57062  /* Here we could remove references to built-ins, but it may not be
57063  * worth the effort because built-ins are quite likely to be shared
57064  * with another (unterminated) thread, and terminated threads are also
57065  * usually garbage collected quite quickly. Also, doing DECREFs
57066  * could trigger finalization, which would run on the current thread
57067  * and have access to only some of the built-ins. Garbage collection
57068  * deals with this correctly already.
57069  */
57070 
57071  /* XXX: Shrink the stacks to minimize memory usage? May not
57072  * be worth the effort because terminated threads are usually
57073  * garbage collected quite soon.
57074  */
57075 }
57076 
57077 DUK_INTERNAL duk_activation *duk_hthread_get_current_activation(duk_hthread *thr) {
57078  DUK_ASSERT(thr != NULL);
57079 
57080  if (thr->callstack_top > 0) {
57081  return thr->callstack + thr->callstack_top - 1;
57082  } else {
57083  return NULL;
57084  }
57085 }
57086 
57087 #if defined(DUK_USE_DEBUGGER_SUPPORT)
57088 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
57089  duk_instr_t *bcode;
57090 
57091  DUK_ASSERT(thr != NULL);
57092  DUK_ASSERT(act != NULL);
57093  DUK_UNREF(thr);
57094 
57095  /* XXX: store 'bcode' pointer to activation for faster lookup? */
57096  if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
57097  bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
57098  return (duk_uint_fast32_t) (act->curr_pc - bcode);
57099  }
57100  return 0;
57101 }
57102 #endif /* DUK_USE_DEBUGGER_SUPPORT */
57103 
57104 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
57105  duk_instr_t *bcode;
57106  duk_uint_fast32_t ret;
57107 
57108  DUK_ASSERT(thr != NULL);
57109  DUK_ASSERT(act != NULL);
57110  DUK_UNREF(thr);
57111 
57112  if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
57113  bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
57114  ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
57115  if (ret > 0) {
57116  ret--;
57117  }
57118  return ret;
57119  }
57120  return 0;
57121 }
57122 
57123 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
57124 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
57125  duk_activation *act;
57126 
57127  DUK_ASSERT(thr != NULL);
57128 
57129  if (thr->ptr_curr_pc != NULL) {
57130  /* ptr_curr_pc != NULL only when bytecode executor is active. */
57131  DUK_ASSERT(thr->callstack_top > 0);
57132  act = thr->callstack + thr->callstack_top - 1;
57133  act->curr_pc = *thr->ptr_curr_pc;
57134  }
57135 }
57136 
57137 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
57138  duk_activation *act;
57139 
57140  DUK_ASSERT(thr != NULL);
57141 
57142  if (thr->ptr_curr_pc != NULL) {
57143  /* ptr_curr_pc != NULL only when bytecode executor is active. */
57144  DUK_ASSERT(thr->callstack_top > 0);
57145  act = thr->callstack + thr->callstack_top - 1;
57146  act->curr_pc = *thr->ptr_curr_pc;
57147  thr->ptr_curr_pc = NULL;
57148  }
57149 }
57150 /*
57151  * Manipulation of thread stacks (valstack, callstack, catchstack).
57152  *
57153  * Ideally unwinding of stacks should have no side effects, which would
57154  * then favor separate unwinding and shrink check primitives for each
57155  * stack type. A shrink check may realloc and thus have side effects.
57156  *
57157  * However, currently callstack unwinding itself has side effects, as it
57158  * needs to DECREF multiple objects, close environment records, etc.
57159  * Stacks must thus be unwound in the correct order by the caller.
57160  *
57161  * (XXX: This should be probably reworked so that there is a shared
57162  * unwind primitive which handles all stacks as requested, and knows
57163  * the proper order for unwinding.)
57164  *
57165  * Valstack entries above 'top' are always kept initialized to
57166  * "undefined unused". Callstack and catchstack entries above 'top'
57167  * are not zeroed and are left as garbage.
57168  *
57169  * Value stack handling is mostly a part of the API implementation.
57170  */
57171 
57172 /* #include duk_internal.h -> already included */
57173 
57174 /* check that there is space for at least one new entry */
57175 DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
57176  duk_activation *new_ptr;
57177  duk_size_t old_size;
57178  duk_size_t new_size;
57179 
57180  DUK_ASSERT(thr != NULL);
57181  DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
57182  DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
57183 
57184  if (thr->callstack_top < thr->callstack_size) {
57185  return;
57186  }
57187 
57188  old_size = thr->callstack_size;
57189  new_size = old_size + DUK_CALLSTACK_GROW_STEP;
57190 
57191  /* this is a bit approximate (errors out before max is reached); this is OK */
57192  if (new_size >= thr->callstack_max) {
57193  DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
57194  }
57195 
57196  DUK_DD(DUK_DDPRINT("growing callstack %ld -> %ld", (long) old_size, (long) new_size));
57197 
57198  /*
57199  * Note: must use indirect variant of DUK_REALLOC() because underlying
57200  * pointer may be changed by mark-and-sweep.
57201  */
57202 
57203  DUK_ASSERT(new_size > 0);
57204  new_ptr = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
57205  if (!new_ptr) {
57206  /* No need for a NULL/zero-size check because new_size > 0) */
57207  DUK_ERROR_ALLOC_FAILED(thr);
57208  }
57209  thr->callstack = new_ptr;
57210  thr->callstack_size = new_size;
57211 
57212  /* note: any entries above the callstack top are garbage and not zeroed */
57213 }
57214 
57215 DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
57216  duk_size_t new_size;
57217  duk_activation *p;
57218 
57219  DUK_ASSERT(thr != NULL);
57220  DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
57221  DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
57222 
57223  if (thr->callstack_size - thr->callstack_top < DUK_CALLSTACK_SHRINK_THRESHOLD) {
57224  return;
57225  }
57226 
57227  new_size = thr->callstack_top + DUK_CALLSTACK_SHRINK_SPARE;
57228  DUK_ASSERT(new_size >= thr->callstack_top);
57229 
57230  DUK_DD(DUK_DDPRINT("shrinking callstack %ld -> %ld", (long) thr->callstack_size, (long) new_size));
57231 
57232  /*
57233  * Note: must use indirect variant of DUK_REALLOC() because underlying
57234  * pointer may be changed by mark-and-sweep.
57235  */
57236 
57237  /* shrink failure is not fatal */
57238  p = (duk_activation *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_callstack_ptr, (void *) thr, sizeof(duk_activation) * new_size);
57239  if (p) {
57240  thr->callstack = p;
57241  thr->callstack_size = new_size;
57242  } else {
57243  /* Because new_size != 0, if condition doesn't need to be
57244  * (p != NULL || new_size == 0).
57245  */
57246  DUK_ASSERT(new_size != 0);
57247  DUK_D(DUK_DPRINT("callstack shrink failed, ignoring"));
57248  }
57249 
57250  /* note: any entries above the callstack top are garbage and not zeroed */
57251 }
57252 
57253 DUK_INTERNAL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
57254  duk_size_t idx;
57255 
57256  DUK_DDD(DUK_DDDPRINT("unwind callstack top of thread %p from %ld to %ld",
57257  (void *) thr,
57258  (thr != NULL ? (long) thr->callstack_top : (long) -1),
57259  (long) new_top));
57260 
57261  DUK_ASSERT(thr);
57262  DUK_ASSERT(thr->heap);
57263  DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
57264  DUK_ASSERT((duk_size_t) new_top <= thr->callstack_top); /* cannot grow */
57265 
57266  /*
57267  * The loop below must avoid issues with potential callstack
57268  * reallocations. A resize (and other side effects) may happen
57269  * e.g. due to finalizer/errhandler calls caused by a refzero or
57270  * mark-and-sweep. Arbitrary finalizers may run, because when
57271  * an environment record is refzero'd, it may refer to arbitrary
57272  * values which also become refzero'd.
57273  *
57274  * So, the pointer 'p' is re-looked-up below whenever a side effect
57275  * might have changed it.
57276  */
57277 
57278  idx = thr->callstack_top;
57279  while (idx > new_top) {
57280  duk_activation *act;
57281  duk_hobject *func;
57282 #if defined(DUK_USE_REFERENCE_COUNTING)
57283  duk_hobject *tmp;
57284 #endif
57285 #if defined(DUK_USE_DEBUGGER_SUPPORT)
57286  duk_heap *heap;
57287 #endif
57288 
57289  idx--;
57290  DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
57291  DUK_ASSERT((duk_size_t) idx < thr->callstack_size); /* true, despite side effect resizes */
57292 
57293  act = thr->callstack + idx;
57294  /* With lightfuncs, act 'func' may be NULL */
57295 
57296 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57297  /*
57298  * Restore 'caller' property for non-strict callee functions.
57299  */
57300 
57301  func = DUK_ACT_GET_FUNC(act);
57302  if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
57303  duk_tval *tv_caller;
57304  duk_tval tv_tmp;
57305  duk_hobject *h_tmp;
57306 
57307  tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
57308 
57309  /* The act->prev_caller should only be set if the entry for 'caller'
57310  * exists (as it is only set in that case, and the property is not
57311  * configurable), but handle all the cases anyway.
57312  */
57313 
57314  if (tv_caller) {
57315  DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
57316  if (act->prev_caller) {
57317  /* Just transfer the refcount from act->prev_caller to tv_caller,
57318  * so no need for a refcount update. This is the expected case.
57319  */
57320  DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
57321  act->prev_caller = NULL;
57322  } else {
57323  DUK_TVAL_SET_NULL(tv_caller); /* no incref needed */
57324  DUK_ASSERT(act->prev_caller == NULL);
57325  }
57326  DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
57327  } else {
57328  h_tmp = act->prev_caller;
57329  if (h_tmp) {
57330  act->prev_caller = NULL;
57331  DUK_HOBJECT_DECREF(thr, h_tmp); /* side effects */
57332  }
57333  }
57334  act = thr->callstack + idx; /* avoid side effects */
57335  DUK_ASSERT(act->prev_caller == NULL);
57336  }
57337 #endif
57338 
57339  /*
57340  * Unwind debugger state. If we unwind while stepping
57341  * (either step over or step into), pause execution.
57342  */
57343 
57344 #if defined(DUK_USE_DEBUGGER_SUPPORT)
57345  heap = thr->heap;
57346  if (heap->dbg_step_thread == thr &&
57347  heap->dbg_step_csindex == idx) {
57348  /* Pause for all step types: step into, step over, step out.
57349  * This is the only place explicitly handling a step out.
57350  */
57351  DUK_HEAP_SET_PAUSED(heap);
57352  DUK_ASSERT(heap->dbg_step_thread == NULL);
57353  }
57354 #endif
57355 
57356  /*
57357  * Close environment record(s) if they exist.
57358  *
57359  * Only variable environments are closed. If lex_env != var_env, it
57360  * cannot currently contain any register bound declarations.
57361  *
57362  * Only environments created for a NEWENV function are closed. If an
57363  * environment is created for e.g. an eval call, it must not be closed.
57364  */
57365 
57366  func = DUK_ACT_GET_FUNC(act);
57367  if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
57368  DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
57369  goto skip_env_close;
57370  }
57371  /* func is NULL for lightfunc */
57372 
57373  DUK_ASSERT(act->lex_env == act->var_env);
57374  if (act->var_env != NULL) {
57375  DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
57376  (void *) act->var_env, (duk_heaphdr *) act->var_env));
57377  duk_js_close_environment_record(thr, act->var_env, func, act->idx_bottom);
57378  act = thr->callstack + idx; /* avoid side effect issues */
57379  }
57380 
57381 #if 0
57382  if (act->lex_env != NULL) {
57383  if (act->lex_env == act->var_env) {
57384  /* common case, already closed, so skip */
57385  DUK_DD(DUK_DDPRINT("lex_env and var_env are the same and lex_env "
57386  "already closed -> skip closing lex_env"));
57387  ;
57388  } else {
57389  DUK_DD(DUK_DDPRINT("closing lex_env record %p -> %!O",
57390  (void *) act->lex_env, (duk_heaphdr *) act->lex_env));
57391  duk_js_close_environment_record(thr, act->lex_env, DUK_ACT_GET_FUNC(act), act->idx_bottom);
57392  act = thr->callstack + idx; /* avoid side effect issues */
57393  }
57394  }
57395 #endif
57396 
57397  DUK_ASSERT((act->lex_env == NULL) ||
57398  ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
57399  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
57400  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
57401  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->lex_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
57402 
57403  DUK_ASSERT((act->var_env == NULL) ||
57404  ((duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL) &&
57405  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_VARMAP(thr)) == NULL) &&
57406  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL) &&
57407  (duk_hobject_find_existing_entry_tval_ptr(thr->heap, act->var_env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL)));
57408 
57409  skip_env_close:
57410 
57411  /*
57412  * Update preventcount
57413  */
57414 
57415  if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
57416  DUK_ASSERT(thr->callstack_preventcount >= 1);
57417  thr->callstack_preventcount--;
57418  }
57419 
57420  /*
57421  * Reference count updates
57422  *
57423  * Note: careful manipulation of refcounts. The top is
57424  * not updated yet, so all the activations are reachable
57425  * for mark-and-sweep (which may be triggered by decref).
57426  * However, the pointers are NULL so this is not an issue.
57427  */
57428 
57429 #if defined(DUK_USE_REFERENCE_COUNTING)
57430  tmp = act->var_env;
57431 #endif
57432  act->var_env = NULL;
57433 #if defined(DUK_USE_REFERENCE_COUNTING)
57434  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
57435  act = thr->callstack + idx; /* avoid side effect issues */
57436 #endif
57437 
57438 #if defined(DUK_USE_REFERENCE_COUNTING)
57439  tmp = act->lex_env;
57440 #endif
57441  act->lex_env = NULL;
57442 #if defined(DUK_USE_REFERENCE_COUNTING)
57443  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
57444  act = thr->callstack + idx; /* avoid side effect issues */
57445 #endif
57446 
57447  /* Note: this may cause a corner case situation where a finalizer
57448  * may see a currently reachable activation whose 'func' is NULL.
57449  */
57450 #if defined(DUK_USE_REFERENCE_COUNTING)
57451  tmp = DUK_ACT_GET_FUNC(act);
57452 #endif
57453  act->func = NULL;
57454 #if defined(DUK_USE_REFERENCE_COUNTING)
57455  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
57456  act = thr->callstack + idx; /* avoid side effect issues */
57457  DUK_UNREF(act);
57458 #endif
57459  }
57460 
57461  thr->callstack_top = new_top;
57462 
57463  /*
57464  * We could clear the book-keeping variables for the topmost activation,
57465  * but don't do so now.
57466  */
57467 #if 0
57468  if (thr->callstack_top > 0) {
57469  duk_activation *act = thr->callstack + thr->callstack_top - 1;
57470  act->idx_retval = 0;
57471  }
57472 #endif
57473 
57474  /* Note: any entries above the callstack top are garbage and not zeroed.
57475  * Also topmost activation idx_retval is garbage (not zeroed), and must
57476  * be ignored.
57477  */
57478 }
57479 
57480 DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
57481  duk_catcher *new_ptr;
57482  duk_size_t old_size;
57483  duk_size_t new_size;
57484 
57485  DUK_ASSERT(thr != NULL);
57486  DUK_ASSERT_DISABLE(thr->catchstack_top); /* avoid warning (unsigned) */
57487  DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
57488 
57489  if (thr->catchstack_top < thr->catchstack_size) {
57490  return;
57491  }
57492 
57493  old_size = thr->catchstack_size;
57494  new_size = old_size + DUK_CATCHSTACK_GROW_STEP;
57495 
57496  /* this is a bit approximate (errors out before max is reached); this is OK */
57497  if (new_size >= thr->catchstack_max) {
57498  DUK_ERROR_RANGE(thr, DUK_STR_CATCHSTACK_LIMIT);
57499  }
57500 
57501  DUK_DD(DUK_DDPRINT("growing catchstack %ld -> %ld", (long) old_size, (long) new_size));
57502 
57503  /*
57504  * Note: must use indirect variant of DUK_REALLOC() because underlying
57505  * pointer may be changed by mark-and-sweep.
57506  */
57507 
57508  DUK_ASSERT(new_size > 0);
57509  new_ptr = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
57510  if (!new_ptr) {
57511  /* No need for a NULL/zero-size check because new_size > 0) */
57512  DUK_ERROR_ALLOC_FAILED(thr);
57513  }
57514  thr->catchstack = new_ptr;
57515  thr->catchstack_size = new_size;
57516 
57517  /* note: any entries above the catchstack top are garbage and not zeroed */
57518 }
57519 
57520 DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
57521  duk_size_t new_size;
57522  duk_catcher *p;
57523 
57524  DUK_ASSERT(thr != NULL);
57525  DUK_ASSERT_DISABLE(thr->catchstack_top >= 0); /* avoid warning (unsigned) */
57526  DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
57527 
57528  if (thr->catchstack_size - thr->catchstack_top < DUK_CATCHSTACK_SHRINK_THRESHOLD) {
57529  return;
57530  }
57531 
57532  new_size = thr->catchstack_top + DUK_CATCHSTACK_SHRINK_SPARE;
57533  DUK_ASSERT(new_size >= thr->catchstack_top);
57534 
57535  DUK_DD(DUK_DDPRINT("shrinking catchstack %ld -> %ld", (long) thr->catchstack_size, (long) new_size));
57536 
57537  /*
57538  * Note: must use indirect variant of DUK_REALLOC() because underlying
57539  * pointer may be changed by mark-and-sweep.
57540  */
57541 
57542  /* shrink failure is not fatal */
57543  p = (duk_catcher *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_catchstack_ptr, (void *) thr, sizeof(duk_catcher) * new_size);
57544  if (p) {
57545  thr->catchstack = p;
57546  thr->catchstack_size = new_size;
57547  } else {
57548  /* Because new_size != 0, if condition doesn't need to be
57549  * (p != NULL || new_size == 0).
57550  */
57551  DUK_ASSERT(new_size != 0);
57552  DUK_D(DUK_DPRINT("catchstack shrink failed, ignoring"));
57553  }
57554 
57555  /* note: any entries above the catchstack top are garbage and not zeroed */
57556 }
57557 
57558 DUK_INTERNAL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
57559  duk_size_t idx;
57560 
57561  DUK_DDD(DUK_DDDPRINT("unwind catchstack top of thread %p from %ld to %ld",
57562  (void *) thr,
57563  (thr != NULL ? (long) thr->catchstack_top : (long) -1),
57564  (long) new_top));
57565 
57566  DUK_ASSERT(thr);
57567  DUK_ASSERT(thr->heap);
57568  DUK_ASSERT_DISABLE(new_top >= 0); /* unsigned */
57569  DUK_ASSERT((duk_size_t) new_top <= thr->catchstack_top); /* cannot grow */
57570 
57571  /*
57572  * Since there are no references in the catcher structure,
57573  * unwinding is quite simple. The only thing we need to
57574  * look out for is popping a possible lexical environment
57575  * established for an active catch clause.
57576  */
57577 
57578  idx = thr->catchstack_top;
57579  while (idx > new_top) {
57580  duk_catcher *p;
57581  duk_activation *act;
57582  duk_hobject *env;
57583 
57584  idx--;
57585  DUK_ASSERT_DISABLE(idx >= 0); /* unsigned */
57586  DUK_ASSERT((duk_size_t) idx < thr->catchstack_size);
57587 
57588  p = thr->catchstack + idx;
57589 
57590  if (DUK_CAT_HAS_LEXENV_ACTIVE(p)) {
57591  DUK_DDD(DUK_DDDPRINT("unwinding catchstack idx %ld, callstack idx %ld, callstack top %ld: lexical environment active",
57592  (long) idx, (long) p->callstack_index, (long) thr->callstack_top));
57593 
57594  /* XXX: Here we have a nasty dependency: the need to manipulate
57595  * the callstack means that catchstack must always be unwound by
57596  * the caller before unwinding the callstack. This should be fixed
57597  * later.
57598  */
57599 
57600  /* Note that multiple catchstack entries may refer to the same
57601  * callstack entry.
57602  */
57603  act = thr->callstack + p->callstack_index;
57604  DUK_ASSERT(act >= thr->callstack);
57605  DUK_ASSERT(act < thr->callstack + thr->callstack_top);
57606 
57607  DUK_DDD(DUK_DDDPRINT("catchstack_index=%ld, callstack_index=%ld, lex_env=%!iO",
57608  (long) idx, (long) p->callstack_index,
57609  (duk_heaphdr *) act->lex_env));
57610 
57611  env = act->lex_env; /* current lex_env of the activation (created for catcher) */
57612  DUK_ASSERT(env != NULL); /* must be, since env was created when catcher was created */
57613  act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env); /* prototype is lex_env before catcher created */
57614  DUK_HOBJECT_DECREF(thr, env);
57615 
57616  /* There is no need to decref anything else than 'env': if 'env'
57617  * becomes unreachable, refzero will handle decref'ing its prototype.
57618  */
57619  }
57620  }
57621 
57622  thr->catchstack_top = new_top;
57623 
57624  /* note: any entries above the catchstack top are garbage and not zeroed */
57625 }
57626 /*
57627  * Shared helpers for arithmetic operations
57628  */
57629 
57630 /* #include duk_internal.h -> already included */
57631 
57632 /* Ecmascript modulus ('%') does not match IEEE 754 "remainder" operation
57633  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
57634  * Compare E5 Section 11.5.3 and "man fmod".
57635  */
57636 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
57637 #if defined(DUK_USE_POW_WORKAROUNDS)
57638  /* Specific fixes to common fmod() implementation issues:
57639  * - test-bug-mingw-math-issues.js
57640  */
57641  if (DUK_ISINF(d2)) {
57642  if (DUK_ISINF(d1)) {
57643  return DUK_DOUBLE_NAN;
57644  } else {
57645  return d1;
57646  }
57647  } else if (d1 == 0.0) {
57648  /* d1 +/-0 is returned as is (preserving sign) except when
57649  * d2 is zero or NaN.
57650  */
57651  if (d2 == 0.0 || DUK_ISNAN(d2)) {
57652  return DUK_DOUBLE_NAN;
57653  } else {
57654  return d1;
57655  }
57656  }
57657 #else
57658  /* Some ISO C assumptions. */
57659  DUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);
57660  DUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);
57661  DUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);
57662  DUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);
57663  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
57664  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
57665  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
57666  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
57667  DUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
57668  DUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
57669  DUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
57670  DUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
57671  DUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
57672  DUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
57673  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
57674  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
57675  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
57676  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
57677  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
57678  DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
57679 #endif
57680 
57681  return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
57682 }
57683 
57684 /* Shared helper for Math.pow() and exponentiation operator. */
57685 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
57686  /* The ANSI C pow() semantics differ from Ecmascript.
57687  *
57688  * E.g. when x==1 and y is +/- infinite, the Ecmascript required
57689  * result is NaN, while at least Linux pow() returns 1.
57690  */
57691 
57692  duk_small_int_t cx, cy, sx;
57693 
57694  DUK_UNREF(cx);
57695  DUK_UNREF(sx);
57696  cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
57697 
57698  if (cy == DUK_FP_NAN) {
57699  goto ret_nan;
57700  }
57701  if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
57702  goto ret_nan;
57703  }
57704 
57705 #if defined(DUK_USE_POW_WORKAROUNDS)
57706  /* Specific fixes to common pow() implementation issues:
57707  * - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
57708  * - test-bug-mingw-math-issues.js
57709  */
57710  cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
57711  if (cx == DUK_FP_ZERO && y < 0.0) {
57712  sx = (duk_small_int_t) DUK_SIGNBIT(x);
57713  if (sx == 0) {
57714  /* Math.pow(+0,y) should be Infinity when y<0. NetBSD pow()
57715  * returns -Infinity instead when y is <0 and finite. The
57716  * if-clause also catches y == -Infinity (which works even
57717  * without the fix).
57718  */
57719  return DUK_DOUBLE_INFINITY;
57720  } else {
57721  /* Math.pow(-0,y) where y<0 should be:
57722  * - -Infinity if y<0 and an odd integer
57723  * - Infinity if y<0 but not an odd integer
57724  * NetBSD pow() returns -Infinity for all finite y<0. The
57725  * if-clause also catches y == -Infinity (which works even
57726  * without the fix).
57727  */
57728 
57729  /* fmod() return value has same sign as input (negative) so
57730  * the result here will be in the range ]-2,0], -1 indicates
57731  * odd. If x is -Infinity, NaN is returned and the odd check
57732  * always concludes "not odd" which results in desired outcome.
57733  */
57734  double tmp = DUK_FMOD(y, 2);
57735  if (tmp == -1.0) {
57736  return -DUK_DOUBLE_INFINITY;
57737  } else {
57738  /* Not odd, or y == -Infinity */
57739  return DUK_DOUBLE_INFINITY;
57740  }
57741  }
57742  } else if (cx == DUK_FP_NAN) {
57743  if (y == 0.0) {
57744  /* NaN ** +/- 0 should always be 1, but is NaN on
57745  * at least some Cygwin/MinGW versions.
57746  */
57747  return 1.0;
57748  }
57749  }
57750 #else
57751  /* Some ISO C assumptions. */
57752  DUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);
57753  DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
57754  DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
57755  DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
57756 #endif
57757 
57758  return DUK_POW(x, y);
57759 
57760  ret_nan:
57761  return DUK_DOUBLE_NAN;
57762 }
57763 /*
57764  * Call handling.
57765  *
57766  * Main functions are:
57767  *
57768  * - duk_handle_call_unprotected(): unprotected call to Ecmascript or
57769  * Duktape/C function
57770  * - duk_handle_call_protected(): protected call to Ecmascript or
57771  * Duktape/C function
57772  * - duk_handle_safe_call(): make a protected C call within current
57773  * activation
57774  * - duk_handle_ecma_call_setup(): Ecmascript-to-Ecmascript calls
57775  * (not always possible), including tail calls and coroutine resume
57776  *
57777  * See 'execution.rst'.
57778  *
57779  * Note: setjmp() and local variables have a nasty interaction,
57780  * see execution.rst; non-volatile locals modified after setjmp()
57781  * call are not guaranteed to keep their value.
57782  */
57783 
57784 /* #include duk_internal.h -> already included */
57785 
57786 /*
57787  * Forward declarations.
57788  */
57789 
57790 DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
57791  duk_idx_t num_stack_args,
57792  duk_small_uint_t call_flags,
57793  duk_idx_t idx_func);
57794 DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
57795  duk_size_t entry_valstack_bottom_index,
57796  duk_size_t entry_valstack_end,
57797  duk_size_t entry_catchstack_top,
57798  duk_size_t entry_callstack_top,
57799  duk_int_t entry_call_recursion_depth,
57800  duk_hthread *entry_curr_thread,
57801  duk_uint_fast8_t entry_thread_state,
57802  duk_instr_t **entry_ptr_curr_pc,
57803  duk_idx_t idx_func,
57804  duk_jmpbuf *old_jmpbuf_ptr);
57805 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
57806  duk_safe_call_function func,
57807  void *udata,
57808  duk_idx_t idx_retbase,
57809  duk_idx_t num_stack_rets,
57810  duk_size_t entry_valstack_bottom_index,
57811  duk_size_t entry_callstack_top,
57812  duk_size_t entry_catchstack_top);
57813 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
57814  duk_idx_t idx_retbase,
57815  duk_idx_t num_stack_rets,
57816  duk_size_t entry_valstack_bottom_index,
57817  duk_size_t entry_callstack_top,
57818  duk_size_t entry_catchstack_top,
57819  duk_jmpbuf *old_jmpbuf_ptr);
57820 DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
57821  duk_idx_t idx_retbase,
57822  duk_idx_t num_stack_rets,
57823  duk_int_t entry_call_recursion_depth,
57824  duk_hthread *entry_curr_thread,
57825  duk_uint_fast8_t entry_thread_state,
57826  duk_instr_t **entry_ptr_curr_pc);
57827 
57828 /*
57829  * Interrupt counter fixup (for development only).
57830  */
57831 
57832 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
57833 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
57834  /* Currently the bytecode executor and executor interrupt
57835  * instruction counts are off because we don't execute the
57836  * interrupt handler when we're about to exit from the initial
57837  * user call into Duktape.
57838  *
57839  * If we were to execute the interrupt handler here, the counts
57840  * would match. You can enable this block manually to check
57841  * that this is the case.
57842  */
57843 
57844  DUK_ASSERT(thr != NULL);
57845  DUK_ASSERT(thr->heap != NULL);
57846 
57847 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
57848  if (entry_curr_thread == NULL) {
57849  thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
57850  thr->heap->inst_count_interrupt += thr->interrupt_init;
57851  DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
57852  "user code, instruction counts: executor=%ld, interrupt=%ld",
57853  (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
57854  DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
57855  }
57856 #else
57857  DUK_UNREF(thr);
57858  DUK_UNREF(entry_curr_thread);
57859 #endif
57860 }
57861 #endif
57862 
57863 /*
57864  * Arguments object creation.
57865  *
57866  * Creating arguments objects involves many small details, see E5 Section
57867  * 10.6 for the specific requirements. Much of the arguments object exotic
57868  * behavior is implemented in duk_hobject_props.c, and is enabled by the
57869  * object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
57870  */
57871 
57872 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
57873  duk_hobject *func,
57874  duk_hobject *varenv,
57875  duk_idx_t idx_argbase, /* idx of first argument on stack */
57876  duk_idx_t num_stack_args) { /* num args starting from idx_argbase */
57877  duk_context *ctx = (duk_context *) thr;
57878  duk_hobject *arg; /* 'arguments' */
57879  duk_hobject *formals; /* formals for 'func' (may be NULL if func is a C function) */
57880  duk_idx_t i_arg;
57881  duk_idx_t i_map;
57882  duk_idx_t i_mappednames;
57883  duk_idx_t i_formals;
57884  duk_idx_t i_argbase;
57885  duk_idx_t n_formals;
57886  duk_idx_t idx;
57887  duk_bool_t need_map;
57888 
57889  DUK_DDD(DUK_DDDPRINT("creating arguments object for func=%!iO, varenv=%!iO, "
57890  "idx_argbase=%ld, num_stack_args=%ld",
57891  (duk_heaphdr *) func, (duk_heaphdr *) varenv,
57892  (long) idx_argbase, (long) num_stack_args));
57893 
57894  DUK_ASSERT(thr != NULL);
57895  DUK_ASSERT(func != NULL);
57896  DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
57897  DUK_ASSERT(varenv != NULL);
57898  DUK_ASSERT(idx_argbase >= 0); /* assumed to bottom relative */
57899  DUK_ASSERT(num_stack_args >= 0);
57900 
57901  need_map = 0;
57902 
57903  i_argbase = idx_argbase;
57904  DUK_ASSERT(i_argbase >= 0);
57905 
57906  duk_push_hobject(ctx, func);
57907  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_FORMALS);
57908  formals = duk_get_hobject(ctx, -1);
57909  if (formals) {
57910  n_formals = (duk_idx_t) duk_get_length(ctx, -1);
57911  } else {
57912  /* This shouldn't happen without tampering of internal
57913  * properties: if a function accesses 'arguments', _Formals
57914  * is kept. Check for the case anyway in case internal
57915  * properties have been modified manually.
57916  */
57917  DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
57918  n_formals = 0;
57919  }
57920  duk_remove_m2(ctx); /* leave formals on stack for later use */
57921  i_formals = duk_require_top_index(ctx);
57922 
57923  DUK_ASSERT(n_formals >= 0);
57924  DUK_ASSERT(formals != NULL || n_formals == 0);
57925 
57926  DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
57927  (duk_heaphdr *) func, (duk_heaphdr *) formals,
57928  (long) n_formals));
57929 
57930  /* [ ... formals ] */
57931 
57932  /*
57933  * Create required objects:
57934  * - 'arguments' object: array-like, but not an array
57935  * - 'map' object: internal object, tied to 'arguments'
57936  * - 'mappedNames' object: temporary value used during construction
57937  */
57938 
57939  arg = duk_push_object_helper(ctx,
57940  DUK_HOBJECT_FLAG_EXTENSIBLE |
57941  DUK_HOBJECT_FLAG_ARRAY_PART |
57942  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
57943  DUK_BIDX_OBJECT_PROTOTYPE);
57944  DUK_ASSERT(arg != NULL);
57945  (void) duk_push_object_helper(ctx,
57946  DUK_HOBJECT_FLAG_EXTENSIBLE |
57947  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
57948  -1); /* no prototype */
57949  (void) duk_push_object_helper(ctx,
57950  DUK_HOBJECT_FLAG_EXTENSIBLE |
57951  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
57952  -1); /* no prototype */
57953  i_arg = duk_get_top(ctx) - 3;
57954  i_map = i_arg + 1;
57955  i_mappednames = i_arg + 2;
57956 
57957  /* [ ... formals arguments map mappedNames ] */
57958 
57959  DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
57960  "arguments at index %ld -> %!O "
57961  "map at index %ld -> %!O "
57962  "mappednames at index %ld -> %!O",
57963  (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
57964  (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
57965  (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
57966 
57967  /*
57968  * Init arguments properties, map, etc.
57969  */
57970 
57971  duk_push_int(ctx, num_stack_args);
57972  duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
57973 
57974  /*
57975  * Init argument related properties
57976  */
57977 
57978  /* step 11 */
57979  idx = num_stack_args - 1;
57980  while (idx >= 0) {
57981  DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
57982  (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
57983 
57984  DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
57985  duk_dup(ctx, i_argbase + idx);
57986  duk_xdef_prop_index_wec(ctx, i_arg, (duk_uarridx_t) idx);
57987  DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
57988 
57989  /* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
57990  if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
57991  DUK_ASSERT(formals != NULL);
57992 
57993  DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
57994  (long) idx, (long) n_formals));
57995 
57996  duk_get_prop_index(ctx, i_formals, idx);
57997  DUK_ASSERT(duk_is_string(ctx, -1));
57998 
57999  duk_dup_top(ctx); /* [ ... name name ] */
58000 
58001  if (!duk_has_prop(ctx, i_mappednames)) {
58002  /* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
58003  * differs from the reference model
58004  */
58005 
58006  /* [ ... name ] */
58007 
58008  need_map = 1;
58009 
58010  DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
58011  (const char *) duk_get_string(ctx, -1),
58012  (long) idx));
58013  duk_dup_top(ctx); /* name */
58014  (void) duk_push_uint_to_hstring(ctx, (duk_uint_t) idx); /* index */
58015  duk_xdef_prop_wec(ctx, i_mappednames); /* out of spec, must be configurable */
58016 
58017  DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
58018  (long) idx,
58019  duk_get_string(ctx, -1)));
58020  duk_dup_top(ctx); /* name */
58021  duk_xdef_prop_index_wec(ctx, i_map, (duk_uarridx_t) idx); /* out of spec, must be configurable */
58022  } else {
58023  /* duk_has_prop() popped the second 'name' */
58024  }
58025 
58026  /* [ ... name ] */
58027  duk_pop(ctx); /* pop 'name' */
58028  }
58029 
58030  idx--;
58031  }
58032 
58033  DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
58034 
58035  /* step 12 */
58036  if (need_map) {
58037  DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
58038 
58039  /* should never happen for a strict callee */
58040  DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
58041 
58042  duk_dup(ctx, i_map);
58043  duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
58044 
58045  /* The variable environment for magic variable bindings needs to be
58046  * given by the caller and recorded in the arguments object.
58047  *
58048  * See E5 Section 10.6, the creation of setters/getters.
58049  *
58050  * The variable environment also provides access to the callee, so
58051  * an explicit (internal) callee property is not needed.
58052  */
58053 
58054  duk_push_hobject(ctx, varenv);
58055  duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE); /* out of spec, don't care */
58056  }
58057 
58058  /* steps 13-14 */
58059  if (DUK_HOBJECT_HAS_STRICT(func)) {
58060  /* Callee/caller are throwers and are not deletable etc. They
58061  * could be implemented as virtual properties, but currently
58062  * there is no support for virtual properties which are accessors
58063  * (only plain virtual properties). This would not be difficult
58064  * to change in duk_hobject_props, but we can make the throwers
58065  * normal, concrete properties just as easily.
58066  *
58067  * Note that the specification requires that the *same* thrower
58068  * built-in object is used here! See E5 Section 10.6 main
58069  * algoritm, step 14, and Section 13.2.3 which describes the
58070  * thrower. See test case test-arguments-throwers.js.
58071  */
58072 
58073  DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
58074 
58075  duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLER);
58076  duk_xdef_prop_stridx_thrower(ctx, i_arg, DUK_STRIDX_CALLEE);
58077  } else {
58078  DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
58079  duk_push_hobject(ctx, func);
58080  duk_xdef_prop_stridx(ctx, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
58081  }
58082 
58083  /* set exotic behavior only after we're done */
58084  if (need_map) {
58085  /* Exotic behaviors are only enabled for arguments objects
58086  * which have a parameter map (see E5 Section 10.6 main
58087  * algorithm, step 12).
58088  *
58089  * In particular, a non-strict arguments object with no
58090  * mapped formals does *NOT* get exotic behavior, even
58091  * for e.g. "caller" property. This seems counterintuitive
58092  * but seems to be the case.
58093  */
58094 
58095  /* cannot be strict (never mapped variables) */
58096  DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
58097 
58098  DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
58099  DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
58100  } else {
58101  DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
58102  }
58103 
58104  DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
58105  "arguments at index %ld -> %!O "
58106  "map at index %ld -> %!O "
58107  "mappednames at index %ld -> %!O",
58108  (long) i_arg, (duk_heaphdr *) duk_get_hobject(ctx, i_arg),
58109  (long) i_map, (duk_heaphdr *) duk_get_hobject(ctx, i_map),
58110  (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(ctx, i_mappednames)));
58111 
58112  /* [ args(n) [crud] formals arguments map mappednames ] */
58113 
58114  duk_pop_2(ctx);
58115  duk_remove_m2(ctx);
58116 
58117  /* [ args [crud] arguments ] */
58118 }
58119 
58120 /* Helper for creating the arguments object and adding it to the env record
58121  * on top of the value stack. This helper has a very strict dependency on
58122  * the shape of the input stack.
58123  */
58124 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
58125  duk_hobject *func,
58126  duk_hobject *env,
58127  duk_idx_t num_stack_args) {
58128  duk_context *ctx = (duk_context *) thr;
58129 
58130  DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
58131 
58132  DUK_ASSERT(thr != NULL);
58133  DUK_ASSERT(func != NULL);
58134  DUK_ASSERT(env != NULL);
58135  DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
58136  DUK_ASSERT(duk_get_top(ctx) >= num_stack_args + 1);
58137 
58138  /* [ ... arg1 ... argN envobj ] */
58139 
58140  duk__create_arguments_object(thr,
58141  func,
58142  env,
58143  duk_get_top(ctx) - num_stack_args - 1, /* idx_argbase */
58144  num_stack_args);
58145 
58146  /* [ ... arg1 ... argN envobj argobj ] */
58147 
58148  duk_xdef_prop_stridx_short(ctx,
58149  -2,
58150  DUK_STRIDX_LC_ARGUMENTS,
58151  DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E : /* strict: non-deletable, non-writable */
58152  DUK_PROPDESC_FLAGS_WE); /* non-strict: non-deletable, writable */
58153  /* [ ... arg1 ... argN envobj ] */
58154 }
58155 
58156 /*
58157  * Helper for handling a "bound function" chain when a call is being made.
58158  *
58159  * Follows the bound function chain until a non-bound function is found.
58160  * Prepends the bound arguments to the value stack (at idx_func + 2),
58161  * updating 'num_stack_args' in the process. The 'this' binding is also
58162  * updated if necessary (at idx_func + 1). Note that for constructor calls
58163  * the 'this' binding is never updated by [[BoundThis]].
58164  *
58165  * XXX: bound function chains could be collapsed at bound function creation
58166  * time so that each bound function would point directly to a non-bound
58167  * function. This would make call time handling much easier.
58168  */
58169 
58170 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
58171  duk_idx_t idx_func,
58172  duk_idx_t *p_num_stack_args, /* may be changed by call */
58173  duk_bool_t is_constructor_call) {
58174  duk_context *ctx = (duk_context *) thr;
58175  duk_idx_t num_stack_args;
58176  duk_tval *tv_func;
58177  duk_hobject *func;
58178  duk_uint_t sanity;
58179 
58180  DUK_ASSERT(thr != NULL);
58181  DUK_ASSERT(p_num_stack_args != NULL);
58182 
58183  /* On entry, item at idx_func is a bound, non-lightweight function,
58184  * but we don't rely on that below.
58185  */
58186 
58187  num_stack_args = *p_num_stack_args;
58188 
58189  sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
58190  do {
58191  duk_idx_t i, len;
58192 
58193  tv_func = duk_require_tval(ctx, idx_func);
58194  DUK_ASSERT(tv_func != NULL);
58195 
58196  if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
58197  /* Lightweight function: never bound, so terminate. */
58198  break;
58199  } else if (DUK_TVAL_IS_OBJECT(tv_func)) {
58200  func = DUK_TVAL_GET_OBJECT(tv_func);
58201  if (!DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
58202  /* Normal non-bound function. */
58203  break;
58204  }
58205  } else {
58206  /* Function.prototype.bind() should never let this happen,
58207  * ugly error message is enough.
58208  */
58209  DUK_ERROR_INTERNAL(thr);
58210  }
58211  DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv_func) != NULL);
58212 
58213  /* XXX: this could be more compact by accessing the internal properties
58214  * directly as own properties (they cannot be inherited, and are not
58215  * externally visible).
58216  */
58217 
58218  DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p, num_stack_args=%ld: %!T",
58219  (void *) DUK_TVAL_GET_OBJECT(tv_func), (long) num_stack_args, tv_func));
58220 
58221  /* [ ... func this arg1 ... argN ] */
58222 
58223  if (is_constructor_call) {
58224  /* See: tests/ecmascript/test-spec-bound-constructor.js */
58225  DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
58226  } else {
58227  duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_THIS);
58228  duk_replace(ctx, idx_func + 1); /* idx_this = idx_func + 1 */
58229  }
58230 
58231  /* [ ... func this arg1 ... argN ] */
58232 
58233  /* XXX: duk_get_length? */
58234  duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_ARGS); /* -> [ ... func this arg1 ... argN _Args ] */
58235  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_LENGTH); /* -> [ ... func this arg1 ... argN _Args length ] */
58236  len = (duk_idx_t) duk_require_int(ctx, -1);
58237  duk_pop(ctx);
58238  for (i = 0; i < len; i++) {
58239  /* XXX: very slow - better to bulk allocate a gap, and copy
58240  * from args_array directly (we know it has a compact array
58241  * part, etc).
58242  */
58243 
58244  /* [ ... func this <some bound args> arg1 ... argN _Args ] */
58245  duk_get_prop_index(ctx, -1, i);
58246  duk_insert(ctx, idx_func + 2 + i); /* idx_args = idx_func + 2 */
58247  }
58248  num_stack_args += len; /* must be updated to work properly (e.g. creation of 'arguments') */
58249  duk_pop(ctx);
58250 
58251  /* [ ... func this <bound args> arg1 ... argN ] */
58252 
58253  duk_get_prop_stridx(ctx, idx_func, DUK_STRIDX_INT_TARGET);
58254  duk_replace(ctx, idx_func); /* replace in stack */
58255 
58256  DUK_DDD(DUK_DDDPRINT("bound function handled, num_stack_args=%ld, idx_func=%ld, curr func=%!T",
58257  (long) num_stack_args, (long) idx_func, duk_get_tval(ctx, idx_func)));
58258  } while (--sanity > 0);
58259 
58260  if (sanity == 0) {
58261  DUK_ERROR_RANGE(thr, DUK_STR_BOUND_CHAIN_LIMIT);
58262  }
58263 
58264  DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(ctx, idx_func)));
58265 
58266 #if defined(DUK_USE_ASSERTIONS)
58267  tv_func = duk_require_tval(ctx, idx_func);
58268  DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
58269  if (DUK_TVAL_IS_OBJECT(tv_func)) {
58270  func = DUK_TVAL_GET_OBJECT(tv_func);
58271  DUK_ASSERT(func != NULL);
58272  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
58273  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
58274  DUK_HOBJECT_HAS_NATFUNC(func));
58275  }
58276 #endif
58277 
58278  /* write back */
58279  *p_num_stack_args = num_stack_args;
58280 }
58281 
58282 /*
58283  * Helper for setting up var_env and lex_env of an activation,
58284  * assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
58285  */
58286 
58287 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
58288  duk_hobject *func,
58289  duk_activation *act) {
58290  duk_hcompfunc *f;
58291  duk_hobject *h_lex;
58292  duk_hobject *h_var;
58293 
58294  DUK_ASSERT(thr != NULL);
58295  DUK_ASSERT(func != NULL);
58296  DUK_ASSERT(act != NULL);
58297  DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
58298  DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
58299  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
58300  DUK_UNREF(thr);
58301 
58302  f = (duk_hcompfunc *) func;
58303  h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
58304  h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
58305  DUK_ASSERT(h_lex != NULL); /* Always true for closures (not for templates) */
58306  DUK_ASSERT(h_var != NULL);
58307  act->lex_env = h_lex;
58308  act->var_env = h_var;
58309  DUK_HOBJECT_INCREF(thr, h_lex);
58310  DUK_HOBJECT_INCREF(thr, h_var);
58311 }
58312 
58313 /*
58314  * Helper for updating callee 'caller' property.
58315  */
58316 
58317 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
58318 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
58319  duk_tval *tv_caller;
58320  duk_hobject *h_tmp;
58321  duk_activation *act_callee;
58322  duk_activation *act_caller;
58323 
58324  DUK_ASSERT(thr != NULL);
58325  DUK_ASSERT(func != NULL);
58326  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound chain resolved */
58327  DUK_ASSERT(thr->callstack_top >= 1);
58328 
58329  if (DUK_HOBJECT_HAS_STRICT(func)) {
58330  /* Strict functions don't get their 'caller' updated. */
58331  return;
58332  }
58333 
58334  act_callee = thr->callstack + thr->callstack_top - 1;
58335  act_caller = (thr->callstack_top >= 2 ? act_callee - 1 : NULL);
58336 
58337  /* XXX: check .caller writability? */
58338 
58339  /* Backup 'caller' property and update its value. */
58340  tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
58341  if (tv_caller) {
58342  /* If caller is global/eval code, 'caller' should be set to
58343  * 'null'.
58344  *
58345  * XXX: there is no exotic flag to infer this correctly now.
58346  * The NEWENV flag is used now which works as intended for
58347  * everything (global code, non-strict eval code, and functions)
58348  * except strict eval code. Bound functions are never an issue
58349  * because 'func' has been resolved to a non-bound function.
58350  */
58351 
58352  if (act_caller) {
58353  /* act_caller->func may be NULL in some finalization cases,
58354  * just treat like we don't know the caller.
58355  */
58356  if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
58357  /* Setting to NULL causes 'caller' to be set to
58358  * 'null' as desired.
58359  */
58360  act_caller = NULL;
58361  }
58362  }
58363 
58364  if (DUK_TVAL_IS_OBJECT(tv_caller)) {
58365  h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
58366  DUK_ASSERT(h_tmp != NULL);
58367  act_callee->prev_caller = h_tmp;
58368 
58369  /* Previous value doesn't need refcount changes because its ownership
58370  * is transferred to prev_caller.
58371  */
58372 
58373  if (act_caller) {
58374  DUK_ASSERT(act_caller->func != NULL);
58375  DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
58376  DUK_TVAL_INCREF(thr, tv_caller);
58377  } else {
58378  DUK_TVAL_SET_NULL(tv_caller); /* no incref */
58379  }
58380  } else {
58381  /* 'caller' must only take on 'null' or function value */
58382  DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
58383  DUK_ASSERT(act_callee->prev_caller == NULL);
58384  if (act_caller && act_caller->func) {
58385  /* Tolerate act_caller->func == NULL which happens in
58386  * some finalization cases; treat like unknown caller.
58387  */
58388  DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
58389  DUK_TVAL_INCREF(thr, tv_caller);
58390  } else {
58391  DUK_TVAL_SET_NULL(tv_caller); /* no incref */
58392  }
58393  }
58394  }
58395 }
58396 #endif /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
58397 
58398 /*
58399  * Determine the effective 'this' binding and coerce the current value
58400  * on the valstack to the effective one (in-place, at idx_this).
58401  *
58402  * The current this value in the valstack (at idx_this) represents either:
58403  * - the caller's requested 'this' binding; or
58404  * - a 'this' binding accumulated from the bound function chain
58405  *
58406  * The final 'this' binding for the target function may still be
58407  * different, and is determined as described in E5 Section 10.4.3.
58408  *
58409  * For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
58410  * that the caller has provided the correct 'this' binding explicitly
58411  * when calling, i.e.:
58412  *
58413  * - global code: this=global object
58414  * - direct eval: this=copy from eval() caller's this binding
58415  * - other eval: this=global object
58416  *
58417  * Note: this function may cause a recursive function call with arbitrary
58418  * side effects, because ToObject() may be called.
58419  */
58420 
58421 DUK_LOCAL void duk__coerce_effective_this_binding(duk_hthread *thr,
58422  duk_hobject *func,
58423  duk_idx_t idx_this) {
58424  duk_context *ctx = (duk_context *) thr;
58425  duk_tval *tv_this;
58426  duk_hobject *obj_global;
58427 
58428  if (func == NULL || DUK_HOBJECT_HAS_STRICT(func)) {
58429  /* Lightfuncs are always considered strict. */
58430  DUK_DDD(DUK_DDDPRINT("this binding: strict -> use directly"));
58431  return;
58432  }
58433 
58434  /* XXX: byte offset */
58435  tv_this = thr->valstack_bottom + idx_this;
58436  switch (DUK_TVAL_GET_TAG(tv_this)) {
58437  case DUK_TAG_OBJECT:
58438  DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
58439  break;
58440  case DUK_TAG_UNDEFINED:
58441  case DUK_TAG_NULL:
58442  DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
58443  obj_global = thr->builtins[DUK_BIDX_GLOBAL];
58444  /* XXX: avoid this check somehow */
58445  if (DUK_LIKELY(obj_global != NULL)) {
58446  DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
58447  DUK_TVAL_SET_OBJECT(tv_this, obj_global);
58448  DUK_HOBJECT_INCREF(thr, obj_global);
58449  } else {
58450  /* This may only happen if built-ins are being "torn down".
58451  * This behavior is out of specification scope.
58452  */
58453  DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
58454  DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this)); /* no need to decref previous value */
58455  DUK_TVAL_SET_UNDEFINED(tv_this); /* nothing to incref */
58456  }
58457  break;
58458  default:
58459  /* Plain buffers and lightfuncs are object coerced. Lightfuncs
58460  * very rarely come here however, because the call target would
58461  * need to be a strict non-lightfunc (lightfuncs are considered
58462  * strict) with an explicit lightfunc 'this' binding.
58463  */
58464  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
58465  DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
58466  duk_to_object(ctx, idx_this); /* may have side effects */
58467  break;
58468  }
58469 }
58470 
58471 /*
58472  * Shared helper for non-bound func lookup.
58473  *
58474  * Returns duk_hobject * to the final non-bound function (NULL for lightfunc).
58475  */
58476 
58477 DUK_LOCAL duk_hobject *duk__nonbound_func_lookup(duk_context *ctx,
58478  duk_idx_t idx_func,
58479  duk_idx_t *out_num_stack_args,
58480  duk_tval **out_tv_func,
58481  duk_small_uint_t call_flags) {
58482  duk_hthread *thr = (duk_hthread *) ctx;
58483  duk_tval *tv_func;
58484  duk_hobject *func;
58485 
58486  for (;;) {
58487  /* Use loop to minimize code size of relookup after bound function case */
58488  tv_func = DUK_GET_TVAL_POSIDX(ctx, idx_func);
58489  DUK_ASSERT(tv_func != NULL);
58490 
58491  if (DUK_TVAL_IS_OBJECT(tv_func)) {
58492  func = DUK_TVAL_GET_OBJECT(tv_func);
58493  if (!DUK_HOBJECT_IS_CALLABLE(func)) {
58494  goto not_callable_error;
58495  }
58496  if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
58497  duk__handle_bound_chain_for_call(thr, idx_func, out_num_stack_args, call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL);
58498 
58499  /* The final object may be a normal function or a lightfunc.
58500  * We need to re-lookup tv_func because it may have changed
58501  * (also value stack may have been resized). Loop again to
58502  * do that; we're guaranteed not to come here again.
58503  */
58504  DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(ctx, idx_func)) ||
58505  DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(ctx, idx_func)));
58506  continue;
58507  }
58508  } else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
58509  func = NULL;
58510  } else {
58511  goto not_callable_error;
58512  }
58513  break;
58514  }
58515 
58516  DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_func) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_func))) ||
58517  DUK_TVAL_IS_LIGHTFUNC(tv_func));
58518  DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
58519  DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
58520  DUK_HOBJECT_IS_NATFUNC(func)));
58521 
58522  *out_tv_func = tv_func;
58523  return func;
58524 
58525  not_callable_error:
58526  DUK_ASSERT(tv_func != NULL);
58527 #if defined(DUK_USE_PARANOID_ERRORS)
58528  DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
58529 #else
58530  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(ctx, tv_func));
58531 #endif
58532  DUK_UNREACHABLE();
58533  return NULL; /* never executed */
58534 }
58535 
58536 /*
58537  * Value stack resize and stack top adjustment helper.
58538  *
58539  * XXX: This should all be merged to duk_valstack_resize_raw().
58540  */
58541 
58542 DUK_LOCAL void duk__adjust_valstack_and_top(duk_hthread *thr,
58543  duk_idx_t num_stack_args,
58544  duk_idx_t idx_args,
58545  duk_idx_t nregs,
58546  duk_idx_t nargs,
58547  duk_hobject *func) {
58548  duk_context *ctx = (duk_context *) thr;
58549  duk_size_t vs_min_size;
58550  duk_bool_t adjusted_top = 0;
58551 
58552  vs_min_size = (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
58553  idx_args; /* bottom of new func */
58554 
58555  if (nregs >= 0) {
58556  DUK_ASSERT(nargs >= 0);
58557  DUK_ASSERT(nregs >= nargs);
58558  vs_min_size += nregs;
58559  } else {
58560  /* 'func' wants stack "as is" */
58561  vs_min_size += num_stack_args; /* num entries of new func at entry */
58562  }
58563  if (func == NULL || DUK_HOBJECT_IS_NATFUNC(func)) {
58564  vs_min_size += DUK_VALSTACK_API_ENTRY_MINIMUM; /* Duktape/C API guaranteed entries (on top of args) */
58565  }
58566  vs_min_size += DUK_VALSTACK_INTERNAL_EXTRA; /* + spare */
58567 
58568  /* XXX: We can't resize the value stack to a size smaller than the
58569  * current top, so the order of the resize and adjusting the stack
58570  * top depends on the current vs. final size of the value stack.
58571  * The operations could be combined to avoid this, but the proper
58572  * fix is to only grow the value stack on a function call, and only
58573  * shrink it (without throwing if the shrink fails) on function
58574  * return.
58575  */
58576 
58577  if (vs_min_size < (duk_size_t) (thr->valstack_top - thr->valstack)) {
58578  DUK_DDD(DUK_DDDPRINT(("final size smaller, set top before resize")));
58579 
58580  DUK_ASSERT(nregs >= 0); /* can't happen when keeping current stack size */
58581  duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
58582  duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
58583  adjusted_top = 1;
58584  }
58585 
58586  (void) duk_valstack_resize_raw((duk_context *) thr,
58587  vs_min_size,
58588  DUK_VSRESIZE_FLAG_SHRINK | /* flags */
58589  0 /* no compact */ |
58590  DUK_VSRESIZE_FLAG_THROW);
58591 
58592  if (!adjusted_top) {
58593  if (nregs >= 0) {
58594  DUK_ASSERT(nregs >= nargs);
58595  duk_set_top(ctx, idx_args + nargs); /* clamp anything above nargs */
58596  duk_set_top(ctx, idx_args + nregs); /* extend with undefined */
58597  }
58598  }
58599 }
58600 
58601 /*
58602  * Manipulate value stack so that exactly 'num_stack_rets' return
58603  * values are at 'idx_retbase' in every case, assuming there are
58604  * 'rc' return values on top of stack.
58605  *
58606  * This is a bit tricky, because the called C function operates in
58607  * the same activation record and may have e.g. popped the stack
58608  * empty (below idx_retbase).
58609  */
58610 
58611 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) {
58612  duk_context *ctx = (duk_context *) thr;
58613  duk_idx_t idx_rcbase;
58614 
58615  DUK_ASSERT(thr != NULL);
58616  DUK_ASSERT(idx_retbase >= 0);
58617  DUK_ASSERT(num_stack_rets >= 0);
58618  DUK_ASSERT(num_actual_rets >= 0);
58619 
58620  idx_rcbase = duk_get_top(ctx) - num_actual_rets; /* base of known return values */
58621 
58622  DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
58623  "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
58624  (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(ctx),
58625  (long) idx_retbase, (long) idx_rcbase));
58626 
58627  DUK_ASSERT(idx_rcbase >= 0); /* caller must check */
58628 
58629  /* Ensure space for final configuration (idx_retbase + num_stack_rets)
58630  * and intermediate configurations.
58631  */
58632  duk_require_stack_top(ctx,
58633  (idx_rcbase > idx_retbase ? idx_rcbase : idx_retbase) +
58634  num_stack_rets);
58635 
58636  /* Chop extra retvals away / extend with undefined. */
58637  duk_set_top(ctx, idx_rcbase + num_stack_rets);
58638 
58639  if (idx_rcbase >= idx_retbase) {
58640  duk_idx_t count = idx_rcbase - idx_retbase;
58641  duk_idx_t i;
58642 
58643  DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
58644  "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
58645 
58646  /* nuke values at idx_retbase to get the first retval (initially
58647  * at idx_rcbase) to idx_retbase
58648  */
58649 
58650  DUK_ASSERT(count >= 0);
58651 
58652  for (i = 0; i < count; i++) {
58653  /* XXX: inefficient; block remove primitive */
58654  duk_remove(ctx, idx_retbase);
58655  }
58656  } else {
58657  duk_idx_t count = idx_retbase - idx_rcbase;
58658  duk_idx_t i;
58659 
58660  DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
58661  "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
58662 
58663  /* insert 'undefined' values at idx_rcbase to get the
58664  * return values to idx_retbase
58665  */
58666 
58667  DUK_ASSERT(count > 0);
58668 
58669  for (i = 0; i < count; i++) {
58670  /* XXX: inefficient; block insert primitive */
58671  duk_push_undefined(ctx);
58672  duk_insert(ctx, idx_rcbase);
58673  }
58674  }
58675 }
58676 
58677 /*
58678  * Misc shared helpers.
58679  */
58680 
58681 /* Get valstack index for the func argument or throw if insane stack. */
58682 DUK_LOCAL duk_idx_t duk__get_idx_func(duk_hthread *thr, duk_idx_t num_stack_args) {
58683  duk_size_t off_stack_top;
58684  duk_size_t off_stack_args;
58685  duk_size_t off_stack_all;
58686  duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
58687 
58688  /* Argument validation and func/args offset. */
58689  off_stack_top = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack_bottom);
58690  off_stack_args = (duk_size_t) ((duk_size_t) num_stack_args * sizeof(duk_tval));
58691  off_stack_all = off_stack_args + 2 * sizeof(duk_tval);
58692  if (DUK_UNLIKELY(off_stack_all > off_stack_top)) {
58693  /* Since stack indices are not reliable, we can't do anything useful
58694  * here. Invoke the existing setjmp catcher, or if it doesn't exist,
58695  * call the fatal error handler.
58696  */
58697  DUK_ERROR_TYPE_INVALID_ARGS(thr);
58698  return 0;
58699  }
58700  idx_func = (duk_idx_t) ((off_stack_top - off_stack_all) / sizeof(duk_tval));
58701  return idx_func;
58702 }
58703 
58704 /*
58705  * duk_handle_call_protected() and duk_handle_call_unprotected():
58706  * call into a Duktape/C or an Ecmascript function from any state.
58707  *
58708  * Input stack (thr):
58709  *
58710  * [ func this arg1 ... argN ]
58711  *
58712  * Output stack (thr):
58713  *
58714  * [ retval ] (DUK_EXEC_SUCCESS)
58715  * [ errobj ] (DUK_EXEC_ERROR (normal error), protected call)
58716  *
58717  * Even when executing a protected call an error may be thrown in rare cases
58718  * such as an insane num_stack_args argument. If there is no catchpoint for
58719  * such errors, the fatal error handler is called.
58720  *
58721  * The error handling path should be error free, even for out-of-memory
58722  * errors, to ensure safe sandboxing. (As of Duktape 1.4.0 this is not
58723  * yet the case, see XXX notes below.)
58724  */
58725 
58726 DUK_INTERNAL duk_int_t duk_handle_call_protected(duk_hthread *thr,
58727  duk_idx_t num_stack_args,
58728  duk_small_uint_t call_flags) {
58729  duk_context *ctx;
58730  duk_size_t entry_valstack_bottom_index;
58731  duk_size_t entry_valstack_end;
58732  duk_size_t entry_callstack_top;
58733  duk_size_t entry_catchstack_top;
58734  duk_int_t entry_call_recursion_depth;
58735  duk_hthread *entry_curr_thread;
58736  duk_uint_fast8_t entry_thread_state;
58737  duk_instr_t **entry_ptr_curr_pc;
58738  duk_jmpbuf *old_jmpbuf_ptr = NULL;
58739  duk_jmpbuf our_jmpbuf;
58740  duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
58741 
58742  /* XXX: Multiple tv_func lookups are now avoided by making a local
58743  * copy of tv_func. Another approach would be to compute an offset
58744  * for tv_func from valstack bottom and recomputing the tv_func
58745  * pointer quickly as valstack + offset instead of calling duk_get_tval().
58746  */
58747 
58748  ctx = (duk_context *) thr;
58749  DUK_UNREF(ctx);
58750  DUK_ASSERT(thr != NULL);
58751  DUK_ASSERT_CTX_VALID(ctx);
58752  DUK_ASSERT(num_stack_args >= 0);
58753  /* XXX: currently NULL allocations are not supported; remove if later allowed */
58754  DUK_ASSERT(thr->valstack != NULL);
58755  DUK_ASSERT(thr->callstack != NULL);
58756  DUK_ASSERT(thr->catchstack != NULL);
58757 
58758  /* Argument validation and func/args offset. */
58759  idx_func = duk__get_idx_func(thr, num_stack_args);
58760 
58761  /* Preliminaries, required by setjmp() handler. Must be careful not
58762  * to throw an unintended error here.
58763  */
58764 
58765  entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
58766 #if defined(DUK_USE_PREFER_SIZE)
58767  entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
58768 #else
58769  DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
58770  entry_valstack_end = thr->valstack_size;
58771 #endif
58772  entry_callstack_top = thr->callstack_top;
58773  entry_catchstack_top = thr->catchstack_top;
58774  entry_call_recursion_depth = thr->heap->call_recursion_depth;
58775  entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
58776  entry_thread_state = thr->state;
58777  entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
58778 
58779  DUK_DD(DUK_DDPRINT("duk_handle_call_protected: thr=%p, num_stack_args=%ld, "
58780  "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
58781  "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
58782  "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
58783  "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
58784  (void *) thr,
58785  (long) num_stack_args,
58786  (unsigned long) call_flags,
58787  (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
58788  (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
58789  (long) duk_get_top(ctx),
58790  (long) idx_func,
58791  (long) (idx_func + 2),
58792  (long) thr->heap->call_recursion_depth,
58793  (long) thr->heap->call_recursion_limit,
58794  (long) entry_valstack_bottom_index,
58795  (long) entry_callstack_top,
58796  (long) entry_catchstack_top,
58797  (long) entry_call_recursion_depth,
58798  (void *) entry_curr_thread,
58799  (long) entry_thread_state));
58800 
58801  old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
58802  thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
58803 
58804 #if defined(DUK_USE_CPP_EXCEPTIONS)
58805  try {
58806 #else
58807  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
58808  if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
58809 #endif
58810  /* Call handling and success path. Success path exit cleans
58811  * up almost all state.
58812  */
58813  duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
58814 
58815  /* Success path handles */
58816  DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
58817  DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
58818 
58819  /* Longjmp state is kept clean in success path */
58820  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
58821  DUK_ASSERT(thr->heap->lj.iserror == 0);
58822  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
58823  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
58824 
58825  thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
58826 
58827  return DUK_EXEC_SUCCESS;
58828 #if defined(DUK_USE_CPP_EXCEPTIONS)
58829  } catch (duk_internal_exception &exc) {
58830 #else
58831  } else {
58832 #endif
58833  /* Error; error value is in heap->lj.value1. */
58834 
58835 #if defined(DUK_USE_CPP_EXCEPTIONS)
58836  DUK_UNREF(exc);
58837 #endif
58838 
58839  duk__handle_call_error(thr,
58840  entry_valstack_bottom_index,
58841  entry_valstack_end,
58842  entry_catchstack_top,
58843  entry_callstack_top,
58844  entry_call_recursion_depth,
58845  entry_curr_thread,
58846  entry_thread_state,
58847  entry_ptr_curr_pc,
58848  idx_func,
58849  old_jmpbuf_ptr);
58850 
58851  /* Longjmp state is cleaned up by error handling */
58852  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
58853  DUK_ASSERT(thr->heap->lj.iserror == 0);
58854  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
58855  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
58856  return DUK_EXEC_ERROR;
58857  }
58858 #if defined(DUK_USE_CPP_EXCEPTIONS)
58859  catch (std::exception &exc) {
58860  const char *what = exc.what();
58861  if (!what) {
58862  what = "unknown";
58863  }
58864  DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
58865  try {
58866  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
58867  } catch (duk_internal_exception exc) {
58868  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
58869  DUK_UNREF(exc);
58870  duk__handle_call_error(thr,
58871  entry_valstack_bottom_index,
58872  entry_valstack_end,
58873  entry_catchstack_top,
58874  entry_callstack_top,
58875  entry_call_recursion_depth,
58876  entry_curr_thread,
58877  entry_thread_state,
58878  entry_ptr_curr_pc,
58879  idx_func,
58880  old_jmpbuf_ptr);
58881  return DUK_EXEC_ERROR;
58882  }
58883  } catch (...) {
58884  DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
58885  try {
58886  DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
58887  } catch (duk_internal_exception exc) {
58888  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
58889  DUK_UNREF(exc);
58890  duk__handle_call_error(thr,
58891  entry_valstack_bottom_index,
58892  entry_valstack_end,
58893  entry_catchstack_top,
58894  entry_callstack_top,
58895  entry_call_recursion_depth,
58896  entry_curr_thread,
58897  entry_thread_state,
58898  entry_ptr_curr_pc,
58899  idx_func,
58900  old_jmpbuf_ptr);
58901  return DUK_EXEC_ERROR;
58902  }
58903  }
58904 #endif
58905 }
58906 
58907 DUK_INTERNAL void duk_handle_call_unprotected(duk_hthread *thr,
58908  duk_idx_t num_stack_args,
58909  duk_small_uint_t call_flags) {
58910  duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
58911 
58912  /* Argument validation and func/args offset. */
58913  idx_func = duk__get_idx_func(thr, num_stack_args);
58914 
58915  duk__handle_call_inner(thr, num_stack_args, call_flags, idx_func);
58916 }
58917 
58918 DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
58919  duk_idx_t num_stack_args,
58920  duk_small_uint_t call_flags,
58921  duk_idx_t idx_func) {
58922  duk_context *ctx;
58923  duk_size_t entry_valstack_bottom_index;
58924  duk_size_t entry_valstack_end;
58925  duk_size_t entry_callstack_top;
58926  duk_size_t entry_catchstack_top;
58927  duk_int_t entry_call_recursion_depth;
58928  duk_hthread *entry_curr_thread;
58929  duk_uint_fast8_t entry_thread_state;
58930  duk_instr_t **entry_ptr_curr_pc;
58931  duk_idx_t nargs; /* # argument registers target function wants (< 0 => "as is") */
58932  duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => "as is") */
58933  duk_hobject *func; /* 'func' on stack (borrowed reference) */
58934  duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) or tv_func_copy */
58935  duk_tval tv_func_copy; /* to avoid relookups */
58936  duk_activation *act;
58937  duk_hobject *env;
58938  duk_ret_t rc;
58939 
58940  ctx = (duk_context *) thr;
58941  DUK_ASSERT(thr != NULL);
58942  DUK_ASSERT_CTX_VALID(ctx);
58943  DUK_ASSERT(ctx != NULL);
58944  DUK_ASSERT(num_stack_args >= 0);
58945  /* XXX: currently NULL allocations are not supported; remove if later allowed */
58946  DUK_ASSERT(thr->valstack != NULL);
58947  DUK_ASSERT(thr->callstack != NULL);
58948  DUK_ASSERT(thr->catchstack != NULL);
58949 
58950  DUK_DD(DUK_DDPRINT("duk__handle_call_inner: num_stack_args=%ld, call_flags=0x%08lx, top=%ld",
58951  (long) num_stack_args, (long) call_flags, (long) duk_get_top(ctx)));
58952 
58953  /*
58954  * Store entry state.
58955  */
58956 
58957  entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
58958 #if defined(DUK_USE_PREFER_SIZE)
58959  entry_valstack_end = (duk_size_t) (thr->valstack_end - thr->valstack);
58960 #else
58961  DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
58962  entry_valstack_end = thr->valstack_size;
58963 #endif
58964  entry_callstack_top = thr->callstack_top;
58965  entry_catchstack_top = thr->catchstack_top;
58966  entry_call_recursion_depth = thr->heap->call_recursion_depth;
58967  entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
58968  entry_thread_state = thr->state;
58969  entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
58970 
58971  /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
58972  * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
58973  * activation when side effects occur.
58974  */
58975  duk_hthread_sync_and_null_currpc(thr);
58976 
58977  DUK_DD(DUK_DDPRINT("duk__handle_call_inner: thr=%p, num_stack_args=%ld, "
58978  "call_flags=0x%08lx (ignorerec=%ld, constructor=%ld), "
58979  "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
58980  "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
58981  "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
58982  (void *) thr,
58983  (long) num_stack_args,
58984  (unsigned long) call_flags,
58985  (long) ((call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) != 0 ? 1 : 0),
58986  (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) != 0 ? 1 : 0),
58987  (long) duk_get_top(ctx),
58988  (long) idx_func,
58989  (long) (idx_func + 2),
58990  (long) thr->heap->call_recursion_depth,
58991  (long) thr->heap->call_recursion_limit,
58992  (long) entry_valstack_bottom_index,
58993  (long) entry_callstack_top,
58994  (long) entry_catchstack_top,
58995  (long) entry_call_recursion_depth,
58996  (void *) entry_curr_thread,
58997  (long) entry_thread_state));
58998 
58999 
59000  /*
59001  * Thread state check and book-keeping.
59002  */
59003 
59004  if (thr == thr->heap->curr_thread) {
59005  /* same thread */
59006  if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
59007  /* should actually never happen, but check anyway */
59008  goto thread_state_error;
59009  }
59010  } else {
59011  /* different thread */
59012  DUK_ASSERT(thr->heap->curr_thread == NULL ||
59013  thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
59014  if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
59015  goto thread_state_error;
59016  }
59017  DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
59018  thr->state = DUK_HTHREAD_STATE_RUNNING;
59019 
59020  /* Note: multiple threads may be simultaneously in the RUNNING
59021  * state, but not in the same "resume chain".
59022  */
59023  }
59024  DUK_ASSERT(thr->heap->curr_thread == thr);
59025  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
59026 
59027  /*
59028  * C call recursion depth check, which provides a reasonable upper
59029  * bound on maximum C stack size (arbitrary C stack growth is only
59030  * possible by recursive handle_call / handle_safe_call calls).
59031  */
59032 
59033  /* XXX: remove DUK_CALL_FLAG_IGNORE_RECLIMIT flag: there's now the
59034  * reclimit bump?
59035  */
59036 
59037  DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
59038  DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
59039  if (call_flags & DUK_CALL_FLAG_IGNORE_RECLIMIT) {
59040  DUK_DD(DUK_DDPRINT("ignoring reclimit for this call (probably an errhandler call)"));
59041  } else {
59042  if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
59043  /* XXX: error message is a bit misleading: we reached a recursion
59044  * limit which is also essentially the same as a C callstack limit
59045  * (except perhaps with some relaxed threading assumptions).
59046  */
59047  DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
59048  }
59049  thr->heap->call_recursion_depth++;
59050  }
59051 
59052  /*
59053  * Check the function type, handle bound function chains, and prepare
59054  * parameters for the rest of the call handling. Also figure out the
59055  * effective 'this' binding, which replaces the current value at
59056  * idx_func + 1.
59057  *
59058  * If the target function is a 'bound' one, follow the chain of 'bound'
59059  * functions until a non-bound function is found. During this process,
59060  * bound arguments are 'prepended' to existing ones, and the "this"
59061  * binding is overridden. See E5 Section 15.3.4.5.1.
59062  *
59063  * Lightfunc detection happens here too. Note that lightweight functions
59064  * can be wrapped by (non-lightweight) bound functions so we must resolve
59065  * the bound function chain first.
59066  */
59067 
59068  func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
59069  DUK_TVAL_SET_TVAL(&tv_func_copy, tv_func);
59070  tv_func = &tv_func_copy; /* local copy to avoid relookups */
59071 
59072  DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
59073  DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
59074  DUK_HOBJECT_IS_NATFUNC(func)));
59075 
59076  duk__coerce_effective_this_binding(thr, func, idx_func + 1);
59077  DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
59078  (duk_tval *) duk_get_tval(ctx, idx_func + 1)));
59079 
59080  /* [ ... func this arg1 ... argN ] */
59081 
59082  /*
59083  * Setup a preliminary activation and figure out nargs/nregs.
59084  *
59085  * Don't touch valstack_bottom or valstack_top yet so that Duktape API
59086  * calls work normally.
59087  */
59088 
59089  duk_hthread_callstack_grow(thr);
59090 
59091  if (thr->callstack_top > 0) {
59092  /*
59093  * Update idx_retval of current activation.
59094  *
59095  * Although it might seem this is not necessary (bytecode executor
59096  * does this for Ecmascript-to-Ecmascript calls; other calls are
59097  * handled here), this turns out to be necessary for handling yield
59098  * and resume. For them, an Ecmascript-to-native call happens, and
59099  * the Ecmascript call's idx_retval must be set for things to work.
59100  */
59101 
59102  (thr->callstack + thr->callstack_top - 1)->idx_retval = entry_valstack_bottom_index + idx_func;
59103  }
59104 
59105  DUK_ASSERT(thr->callstack_top < thr->callstack_size);
59106  act = thr->callstack + thr->callstack_top;
59107  thr->callstack_top++;
59108  DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
59109  DUK_ASSERT(thr->valstack_top > thr->valstack_bottom); /* at least effective 'this' */
59110  DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
59111 
59112  act->flags = 0;
59113 
59114  /* For now all calls except Ecma-to-Ecma calls prevent a yield. */
59115  act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
59116  if (call_flags & DUK_CALL_FLAG_CONSTRUCTOR_CALL) {
59117  act->flags |= DUK_ACT_FLAG_CONSTRUCT;
59118  }
59119  if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
59120  act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
59121  }
59122 
59123  /* These base values are never used, but if the compiler doesn't know
59124  * that DUK_ERROR() won't return, these are needed to silence warnings.
59125  * On the other hand, scan-build will warn about the values not being
59126  * used, so add a DUK_UNREF.
59127  */
59128  nargs = 0; DUK_UNREF(nargs);
59129  nregs = 0; DUK_UNREF(nregs);
59130 
59131  if (DUK_LIKELY(func != NULL)) {
59132  if (DUK_HOBJECT_HAS_STRICT(func)) {
59133  act->flags |= DUK_ACT_FLAG_STRICT;
59134  }
59135  if (DUK_HOBJECT_IS_COMPFUNC(func)) {
59136  nargs = ((duk_hcompfunc *) func)->nargs;
59137  nregs = ((duk_hcompfunc *) func)->nregs;
59138  DUK_ASSERT(nregs >= nargs);
59139  } else {
59140  /* True because of call target lookup checks. */
59141  DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
59142 
59143  /* Note: nargs (and nregs) may be negative for a native,
59144  * function, which indicates that the function wants the
59145  * input stack "as is" (i.e. handles "vararg" arguments).
59146  */
59147  nargs = ((duk_hnatfunc *) func)->nargs;
59148  nregs = nargs;
59149  }
59150  } else {
59151  duk_small_uint_t lf_flags;
59152 
59153  DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
59154  lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
59155  nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
59156  if (nargs == DUK_LFUNC_NARGS_VARARGS) {
59157  nargs = -1; /* vararg */
59158  }
59159  nregs = nargs;
59160 
59161  act->flags |= DUK_ACT_FLAG_STRICT;
59162  }
59163 
59164  act->func = func; /* NULL for lightfunc */
59165  act->var_env = NULL;
59166  act->lex_env = NULL;
59167 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
59168  act->prev_caller = NULL;
59169 #endif
59170  act->curr_pc = NULL;
59171 #if defined(DUK_USE_DEBUGGER_SUPPORT)
59172  act->prev_line = 0;
59173 #endif
59174  act->idx_bottom = entry_valstack_bottom_index + idx_func + 2;
59175 #if 0 /* topmost activation idx_retval is considered garbage, no need to init */
59176  act->idx_retval = 0;
59177 #endif
59178  DUK_TVAL_SET_TVAL(&act->tv_func, tv_func); /* borrowed, no refcount */
59179 
59180  /* XXX: remove the preventcount and make yield walk the callstack?
59181  * Or perhaps just use a single flag, not a counter, faster to just
59182  * set and restore?
59183  */
59184  if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
59185  /* duk_hthread_callstack_unwind() will decrease this on unwind */
59186  thr->callstack_preventcount++;
59187  }
59188 
59189  /* XXX: Is this INCREF necessary? 'func' is always a borrowed
59190  * reference reachable through the value stack? If changed, stack
59191  * unwind code also needs to be fixed to match.
59192  */
59193  DUK_HOBJECT_INCREF_ALLOWNULL(thr, func); /* act->func */
59194 
59195 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
59196  if (func) {
59197  duk__update_func_caller_prop(thr, func);
59198  }
59199  act = thr->callstack + thr->callstack_top - 1;
59200 #endif
59201 
59202  /* [ ... func this arg1 ... argN ] */
59203 
59204  /*
59205  * Environment record creation and 'arguments' object creation.
59206  * Named function expression name binding is handled by the
59207  * compiler; the compiled function's parent env will contain
59208  * the (immutable) binding already.
59209  *
59210  * This handling is now identical for C and Ecmascript functions.
59211  * C functions always have the 'NEWENV' flag set, so their
59212  * environment record initialization is delayed (which is good).
59213  *
59214  * Delayed creation (on demand) is handled in duk_js_var.c.
59215  */
59216 
59217  DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound function chain has already been resolved */
59218 
59219  if (DUK_LIKELY(func != NULL)) {
59220  if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
59221  if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
59222  /* Use a new environment but there's no 'arguments' object;
59223  * delayed environment initialization. This is the most
59224  * common case.
59225  */
59226  DUK_ASSERT(act->lex_env == NULL);
59227  DUK_ASSERT(act->var_env == NULL);
59228  } else {
59229  /* Use a new environment and there's an 'arguments' object.
59230  * We need to initialize it right now.
59231  */
59232 
59233  /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
59234  env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
59235  DUK_ASSERT(env != NULL);
59236 
59237  /* [ ... func this arg1 ... argN envobj ] */
59238 
59239  DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
59240  duk__handle_createargs_for_call(thr, func, env, num_stack_args);
59241 
59242  /* [ ... func this arg1 ... argN envobj ] */
59243 
59244  act = thr->callstack + thr->callstack_top - 1;
59245  act->lex_env = env;
59246  act->var_env = env;
59247  DUK_HOBJECT_INCREF(thr, env);
59248  DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (2) directly */
59249  duk_pop(ctx);
59250  }
59251  } else {
59252  /* Use existing env (e.g. for non-strict eval); cannot have
59253  * an own 'arguments' object (but can refer to an existing one).
59254  */
59255 
59256  DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
59257 
59258  duk__handle_oldenv_for_call(thr, func, act);
59259 
59260  DUK_ASSERT(act->lex_env != NULL);
59261  DUK_ASSERT(act->var_env != NULL);
59262  }
59263  } else {
59264  /* Lightfuncs are always native functions and have "newenv". */
59265  DUK_ASSERT(act->lex_env == NULL);
59266  DUK_ASSERT(act->var_env == NULL);
59267  }
59268 
59269  /* [ ... func this arg1 ... argN ] */
59270 
59271  /*
59272  * Setup value stack: clamp to 'nargs', fill up to 'nregs'
59273  *
59274  * Value stack may either grow or shrink, depending on the
59275  * number of func registers and the number of actual arguments.
59276  * If nregs >= 0, func wants args clamped to 'nargs'; else it
59277  * wants all args (= 'num_stack_args').
59278  */
59279 
59280  /* XXX: optimize value stack operation */
59281  /* XXX: don't want to shrink allocation here */
59282 
59283  duk__adjust_valstack_and_top(thr,
59284  num_stack_args,
59285  idx_func + 2,
59286  nregs,
59287  nargs,
59288  func);
59289 
59290  /*
59291  * Determine call type, then finalize activation, shift to
59292  * new value stack bottom, and call the target.
59293  */
59294 
59295  if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
59296  /*
59297  * Ecmascript call
59298  */
59299 
59300  duk_tval *tv_ret;
59301  duk_tval *tv_funret;
59302 
59303  DUK_ASSERT(func != NULL);
59304  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
59305  act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
59306 
59307  thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
59308  /* keep current valstack_top */
59309  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
59310  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
59311  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
59312 
59313  /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
59314 
59315  /*
59316  * Bytecode executor call.
59317  *
59318  * Execute bytecode, handling any recursive function calls and
59319  * thread resumptions. Returns when execution would return from
59320  * the entry level activation. When the executor returns, a
59321  * single return value is left on the stack top.
59322  *
59323  * The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
59324  * other types are handled internally by the executor.
59325  */
59326 
59327  /* thr->ptr_curr_pc is set by bytecode executor early on entry */
59328  DUK_ASSERT(thr->ptr_curr_pc == NULL);
59329  DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
59330  duk_js_execute_bytecode(thr);
59331  DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
59332 
59333  /* Unwind. */
59334 
59335  DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top); /* may need unwind */
59336  DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
59337  DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
59338  duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
59339  duk_hthread_catchstack_shrink_check(thr);
59340  duk_hthread_callstack_unwind(thr, entry_callstack_top);
59341  duk_hthread_callstack_shrink_check(thr);
59342 
59343  thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
59344  /* keep current valstack_top */
59345  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
59346  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
59347  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
59348  DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
59349 
59350  /* Return value handling. */
59351 
59352  /* [ ... func this (crud) retval ] */
59353 
59354  tv_ret = thr->valstack_bottom + idx_func;
59355  tv_funret = thr->valstack_top - 1;
59356 #if defined(DUK_USE_FASTINT)
59357  /* Explicit check for fastint downgrade. */
59358  DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
59359 #endif
59360  DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
59361  } else {
59362  /*
59363  * Native call.
59364  */
59365 
59366  duk_tval *tv_ret;
59367  duk_tval *tv_funret;
59368 
59369  thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
59370  /* keep current valstack_top */
59371  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
59372  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
59373  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
59374  DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
59375 
59376  /* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
59377 
59378  /* For native calls must be NULL so we don't sync back */
59379  DUK_ASSERT(thr->ptr_curr_pc == NULL);
59380 
59381  if (func) {
59382  rc = ((duk_hnatfunc *) func)->func((duk_context *) thr);
59383  } else {
59384  duk_c_function funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
59385  rc = funcptr((duk_context *) thr);
59386  }
59387 
59388  /* Automatic error throwing, retval check. */
59389 
59390  if (rc < 0) {
59391  duk_error_throw_from_negative_rc(thr, rc);
59392  DUK_UNREACHABLE();
59393  } else if (rc > 1) {
59394  DUK_ERROR_TYPE(thr, "c function returned invalid rc");
59395  }
59396  DUK_ASSERT(rc == 0 || rc == 1);
59397 
59398  /* Unwind. */
59399 
59400  DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
59401  DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
59402  duk_hthread_callstack_unwind(thr, entry_callstack_top);
59403  duk_hthread_callstack_shrink_check(thr);
59404 
59405  thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
59406  /* keep current valstack_top */
59407  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
59408  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
59409  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
59410  DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
59411 
59412  /* Return value handling. */
59413 
59414  /* XXX: should this happen in the callee's activation or after unwinding? */
59415  tv_ret = thr->valstack_bottom + idx_func;
59416  if (rc == 0) {
59417  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv_ret); /* side effects */
59418  } else {
59419  /* [ ... func this (crud) retval ] */
59420  tv_funret = thr->valstack_top - 1;
59421 #if defined(DUK_USE_FASTINT)
59422  /* Explicit check for fastint downgrade. */
59423  DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
59424 #endif
59425  DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
59426  }
59427  }
59428 
59429  duk_set_top(ctx, idx_func + 1); /* XXX: unnecessary, handle in adjust */
59430 
59431  /* [ ... retval ] */
59432 
59433  /* Ensure there is internal valstack spare before we exit; this may
59434  * throw an alloc error. The same guaranteed size must be available
59435  * as before the call. This is not optimal now: we store the valstack
59436  * allocated size during entry; this value may be higher than the
59437  * minimal guarantee for an application.
59438  */
59439 
59440  /* XXX: we should never shrink here; when we error out later, we'd
59441  * need to potentially grow the value stack in error unwind which could
59442  * cause another error.
59443  */
59444 
59445  (void) duk_valstack_resize_raw((duk_context *) thr,
59446  entry_valstack_end, /* same as during entry */
59447  DUK_VSRESIZE_FLAG_SHRINK | /* flags */
59448  DUK_VSRESIZE_FLAG_COMPACT |
59449  DUK_VSRESIZE_FLAG_THROW);
59450 
59451  /* Restore entry thread executor curr_pc stack frame pointer. */
59452  thr->ptr_curr_pc = entry_ptr_curr_pc;
59453 
59454  DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
59455  thr->state = (duk_uint8_t) entry_thread_state;
59456 
59457  DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
59458  (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
59459  (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
59460 
59461  thr->heap->call_recursion_depth = entry_call_recursion_depth;
59462 
59463  /* If the debugger is active we need to force an interrupt so that
59464  * debugger breakpoints are rechecked. This is important for function
59465  * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
59466  * GH-303. Only needed for success path, error path always causes a
59467  * breakpoint recheck in the executor. It would be enough to set this
59468  * only when returning to an Ecmascript activation, but setting the flag
59469  * on every return should have no ill effect.
59470  */
59471 #if defined(DUK_USE_DEBUGGER_SUPPORT)
59472  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
59473  DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
59474  DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
59475  thr->interrupt_init -= thr->interrupt_counter;
59476  thr->interrupt_counter = 0;
59477  thr->heap->dbg_force_restart = 1;
59478  }
59479 #endif
59480 
59481 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
59482  duk__interrupt_fixup(thr, entry_curr_thread);
59483 #endif
59484 
59485  return;
59486 
59487  thread_state_error:
59488  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for call (%ld)", (long) thr->state);
59489  DUK_UNREACHABLE();
59490  return; /* never executed */
59491 }
59492 
59493 DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
59494  duk_size_t entry_valstack_bottom_index,
59495  duk_size_t entry_valstack_end,
59496  duk_size_t entry_catchstack_top,
59497  duk_size_t entry_callstack_top,
59498  duk_int_t entry_call_recursion_depth,
59499  duk_hthread *entry_curr_thread,
59500  duk_uint_fast8_t entry_thread_state,
59501  duk_instr_t **entry_ptr_curr_pc,
59502  duk_idx_t idx_func,
59503  duk_jmpbuf *old_jmpbuf_ptr) {
59504  duk_context *ctx;
59505  duk_tval *tv_ret;
59506 
59507  ctx = (duk_context *) thr;
59508 
59509  DUK_DDD(DUK_DDDPRINT("error caught during duk__handle_call_inner(): %!T",
59510  (duk_tval *) &thr->heap->lj.value1));
59511 
59512  /* Other longjmp types are handled by executor before propagating
59513  * the error here.
59514  */
59515  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
59516  DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
59517  DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
59518 
59519  /* We don't need to sync back thr->ptr_curr_pc here because
59520  * the bytecode executor always has a setjmp catchpoint which
59521  * does that before errors propagate to here.
59522  */
59523  DUK_ASSERT(thr->ptr_curr_pc == NULL);
59524 
59525  /* Restore the previous setjmp catcher so that any error in
59526  * error handling will propagate outwards rather than re-enter
59527  * the same handler. However, the error handling path must be
59528  * designed to be error free so that sandboxing guarantees are
59529  * reliable, see e.g. https://github.com/svaarala/duktape/issues/476.
59530  */
59531  thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
59532 
59533  /* XXX: callstack unwind may now throw an error when closing
59534  * scopes; this is a sandboxing issue, described in:
59535  * https://github.com/svaarala/duktape/issues/476
59536  */
59537  duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
59538  duk_hthread_catchstack_shrink_check(thr);
59539  duk_hthread_callstack_unwind(thr, entry_callstack_top);
59540  duk_hthread_callstack_shrink_check(thr);
59541 
59542  thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
59543  tv_ret = thr->valstack_bottom + idx_func; /* XXX: byte offset? */
59544  DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1); /* side effects */
59545 #if defined(DUK_USE_FASTINT)
59546  /* Explicit check for fastint downgrade. */
59547  DUK_TVAL_CHKFAST_INPLACE_FAST(tv_ret);
59548 #endif
59549  duk_set_top(ctx, idx_func + 1); /* XXX: could be eliminated with valstack adjust */
59550 
59551  /* [ ... errobj ] */
59552 
59553  /* Ensure there is internal valstack spare before we exit; this may
59554  * throw an alloc error. The same guaranteed size must be available
59555  * as before the call. This is not optimal now: we store the valstack
59556  * allocated size during entry; this value may be higher than the
59557  * minimal guarantee for an application.
59558  */
59559 
59560  /* XXX: this needs to be reworked so that we never shrink the value
59561  * stack on function entry so that we never need to grow it here.
59562  * Needing to grow here is a sandboxing issue because we need to
59563  * allocate which may cause an error in the error handling path
59564  * and thus propagate an error out of a protected call.
59565  */
59566 
59567  (void) duk_valstack_resize_raw((duk_context *) thr,
59568  entry_valstack_end, /* same as during entry */
59569  DUK_VSRESIZE_FLAG_SHRINK | /* flags */
59570  DUK_VSRESIZE_FLAG_COMPACT |
59571  DUK_VSRESIZE_FLAG_THROW);
59572 
59573 
59574  /* These are just convenience "wiping" of state. Side effects should
59575  * not be an issue here: thr->heap and thr->heap->lj have a stable
59576  * pointer. Finalizer runs etc capture even out-of-memory errors so
59577  * nothing should throw here.
59578  */
59579  thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
59580  thr->heap->lj.iserror = 0;
59581  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
59582  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
59583 
59584  /* Restore entry thread executor curr_pc stack frame pointer. */
59585  thr->ptr_curr_pc = entry_ptr_curr_pc;
59586 
59587  DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
59588  thr->state = (duk_uint8_t) entry_thread_state;
59589 
59590  DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
59591  (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
59592  (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
59593 
59594  thr->heap->call_recursion_depth = entry_call_recursion_depth;
59595 
59596  /* If the debugger is active we need to force an interrupt so that
59597  * debugger breakpoints are rechecked. This is important for function
59598  * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
59599  * GH-303. Only needed for success path, error path always causes a
59600  * breakpoint recheck in the executor. It would be enough to set this
59601  * only when returning to an Ecmascript activation, but setting the flag
59602  * on every return should have no ill effect.
59603  */
59604 #if defined(DUK_USE_DEBUGGER_SUPPORT)
59605  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
59606  DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
59607  DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
59608  thr->interrupt_init -= thr->interrupt_counter;
59609  thr->interrupt_counter = 0;
59610  thr->heap->dbg_force_restart = 1;
59611  }
59612 #endif
59613 
59614 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
59615  duk__interrupt_fixup(thr, entry_curr_thread);
59616 #endif
59617 }
59618 
59619 /*
59620  * duk_handle_safe_call(): make a "C protected call" within the
59621  * current activation.
59622  *
59623  * The allowed thread states for making a call are the same as for
59624  * duk_handle_call_xxx().
59625  *
59626  * Error handling is similar to duk_handle_call_xxx(); errors may be thrown
59627  * (and result in a fatal error) for insane arguments.
59628  */
59629 
59630 /* XXX: bump preventcount by one for the duration of this call? */
59631 
59632 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
59633  duk_safe_call_function func,
59634  void *udata,
59635  duk_idx_t num_stack_args,
59636  duk_idx_t num_stack_rets) {
59637  duk_context *ctx = (duk_context *) thr;
59638  duk_size_t entry_valstack_bottom_index;
59639  duk_size_t entry_callstack_top;
59640  duk_size_t entry_catchstack_top;
59641  duk_int_t entry_call_recursion_depth;
59642  duk_hthread *entry_curr_thread;
59643  duk_uint_fast8_t entry_thread_state;
59644  duk_instr_t **entry_ptr_curr_pc;
59645  duk_jmpbuf *old_jmpbuf_ptr = NULL;
59646  duk_jmpbuf our_jmpbuf;
59647  duk_idx_t idx_retbase;
59648  duk_int_t retval;
59649 
59650  DUK_ASSERT(thr != NULL);
59651  DUK_ASSERT(ctx != NULL);
59652 
59653  /* Note: careful with indices like '-x'; if 'x' is zero, it refers to bottom */
59654  entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
59655  entry_callstack_top = thr->callstack_top;
59656  entry_catchstack_top = thr->catchstack_top;
59657  entry_call_recursion_depth = thr->heap->call_recursion_depth;
59658  entry_curr_thread = thr->heap->curr_thread; /* Note: may be NULL if first call */
59659  entry_thread_state = thr->state;
59660  entry_ptr_curr_pc = thr->ptr_curr_pc; /* may be NULL */
59661  idx_retbase = duk_get_top(ctx) - num_stack_args; /* Note: not a valid stack index if num_stack_args == 0 */
59662 
59663  /* Note: cannot portably debug print a function pointer, hence 'func' not printed! */
59664  DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
59665  "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
59666  "entry_valstack_bottom_index=%ld, entry_callstack_top=%ld, entry_catchstack_top=%ld, "
59667  "entry_call_recursion_depth=%ld, entry_curr_thread=%p, entry_thread_state=%ld",
59668  (void *) thr,
59669  (long) num_stack_args,
59670  (long) num_stack_rets,
59671  (long) duk_get_top(ctx),
59672  (long) idx_retbase,
59673  (long) thr->heap->call_recursion_depth,
59674  (long) thr->heap->call_recursion_limit,
59675  (long) entry_valstack_bottom_index,
59676  (long) entry_callstack_top,
59677  (long) entry_catchstack_top,
59678  (long) entry_call_recursion_depth,
59679  (void *) entry_curr_thread,
59680  (long) entry_thread_state));
59681 
59682  if (idx_retbase < 0) {
59683  /* Since stack indices are not reliable, we can't do anything useful
59684  * here. Invoke the existing setjmp catcher, or if it doesn't exist,
59685  * call the fatal error handler.
59686  */
59687 
59688  DUK_ERROR_TYPE_INVALID_ARGS(thr);
59689  }
59690 
59691  /* setjmp catchpoint setup */
59692 
59693  old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
59694  thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
59695 
59696 #if defined(DUK_USE_CPP_EXCEPTIONS)
59697  try {
59698 #else
59699  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
59700  if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
59701  /* Success path. */
59702 #endif
59703  DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
59704 
59705  duk__handle_safe_call_inner(thr,
59706  func,
59707  udata,
59708  idx_retbase,
59709  num_stack_rets,
59710  entry_valstack_bottom_index,
59711  entry_callstack_top,
59712  entry_catchstack_top);
59713 
59714  /* Longjmp state is kept clean in success path */
59715  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
59716  DUK_ASSERT(thr->heap->lj.iserror == 0);
59717  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
59718  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
59719 
59720  /* Note: either pointer may be NULL (at entry), so don't assert */
59721  thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
59722 
59723  retval = DUK_EXEC_SUCCESS;
59724 #if defined(DUK_USE_CPP_EXCEPTIONS)
59725  } catch (duk_internal_exception &exc) {
59726  DUK_UNREF(exc);
59727 #else
59728  } else {
59729  /* Error path. */
59730 #endif
59731  duk__handle_safe_call_error(thr,
59732  idx_retbase,
59733  num_stack_rets,
59734  entry_valstack_bottom_index,
59735  entry_callstack_top,
59736  entry_catchstack_top,
59737  old_jmpbuf_ptr);
59738 
59739  /* Longjmp state is cleaned up by error handling */
59740  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_UNKNOWN);
59741  DUK_ASSERT(thr->heap->lj.iserror == 0);
59742  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
59743  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
59744 
59745  retval = DUK_EXEC_ERROR;
59746  }
59747 #if defined(DUK_USE_CPP_EXCEPTIONS)
59748  catch (std::exception &exc) {
59749  const char *what = exc.what();
59750  if (!what) {
59751  what = "unknown";
59752  }
59753  DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
59754  try {
59755  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
59756  } catch (duk_internal_exception exc) {
59757  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
59758  DUK_UNREF(exc);
59759  duk__handle_safe_call_error(thr,
59760  idx_retbase,
59761  num_stack_rets,
59762  entry_valstack_bottom_index,
59763  entry_callstack_top,
59764  entry_catchstack_top,
59765  old_jmpbuf_ptr);
59766  retval = DUK_EXEC_ERROR;
59767  }
59768  } catch (...) {
59769  DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
59770  try {
59771  DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
59772  } catch (duk_internal_exception exc) {
59773  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
59774  DUK_UNREF(exc);
59775  duk__handle_safe_call_error(thr,
59776  idx_retbase,
59777  num_stack_rets,
59778  entry_valstack_bottom_index,
59779  entry_callstack_top,
59780  entry_catchstack_top,
59781  old_jmpbuf_ptr);
59782  retval = DUK_EXEC_ERROR;
59783  }
59784  }
59785 #endif
59786 
59787  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr); /* success/error path both do this */
59788 
59789  duk__handle_safe_call_shared(thr,
59790  idx_retbase,
59791  num_stack_rets,
59792  entry_call_recursion_depth,
59793  entry_curr_thread,
59794  entry_thread_state,
59795  entry_ptr_curr_pc);
59796 
59797  return retval;
59798 }
59799 
59800 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
59801  duk_safe_call_function func,
59802  void *udata,
59803  duk_idx_t idx_retbase,
59804  duk_idx_t num_stack_rets,
59805  duk_size_t entry_valstack_bottom_index,
59806  duk_size_t entry_callstack_top,
59807  duk_size_t entry_catchstack_top) {
59808  duk_context *ctx;
59809  duk_ret_t rc;
59810 
59811  DUK_ASSERT(thr != NULL);
59812  ctx = (duk_context *) thr;
59813  DUK_ASSERT_CTX_VALID(ctx);
59814  DUK_UNREF(entry_valstack_bottom_index);
59815  DUK_UNREF(entry_callstack_top);
59816  DUK_UNREF(entry_catchstack_top);
59817 
59818  /*
59819  * Thread state check and book-keeping.
59820  */
59821 
59822  if (thr == thr->heap->curr_thread) {
59823  /* same thread */
59824  if (thr->state != DUK_HTHREAD_STATE_RUNNING) {
59825  /* should actually never happen, but check anyway */
59826  goto thread_state_error;
59827  }
59828  } else {
59829  /* different thread */
59830  DUK_ASSERT(thr->heap->curr_thread == NULL ||
59831  thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
59832  if (thr->state != DUK_HTHREAD_STATE_INACTIVE) {
59833  goto thread_state_error;
59834  }
59835  DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
59836  thr->state = DUK_HTHREAD_STATE_RUNNING;
59837 
59838  /* Note: multiple threads may be simultaneously in the RUNNING
59839  * state, but not in the same "resume chain".
59840  */
59841  }
59842 
59843  DUK_ASSERT(thr->heap->curr_thread == thr);
59844  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
59845 
59846  /*
59847  * Recursion limit check.
59848  *
59849  * Note: there is no need for an "ignore recursion limit" flag
59850  * for duk_handle_safe_call now.
59851  */
59852 
59853  DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
59854  DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
59855  if (thr->heap->call_recursion_depth >= thr->heap->call_recursion_limit) {
59856  /* XXX: error message is a bit misleading: we reached a recursion
59857  * limit which is also essentially the same as a C callstack limit
59858  * (except perhaps with some relaxed threading assumptions).
59859  */
59860  DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
59861  }
59862  thr->heap->call_recursion_depth++;
59863 
59864  /*
59865  * Valstack spare check
59866  */
59867 
59868  duk_require_stack(ctx, 0); /* internal spare */
59869 
59870  /*
59871  * Make the C call
59872  */
59873 
59874  rc = func(ctx, udata);
59875 
59876  DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
59877 
59878  /*
59879  * Valstack manipulation for results.
59880  */
59881 
59882  /* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
59883  DUK_ASSERT(thr->callstack_top == entry_callstack_top);
59884  DUK_ASSERT(thr->catchstack_top == entry_catchstack_top);
59885  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
59886  DUK_ASSERT((duk_size_t) (thr->valstack_bottom - thr->valstack) == entry_valstack_bottom_index);
59887  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
59888  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
59889 
59890  if (rc < 0) {
59891  duk_error_throw_from_negative_rc(thr, rc);
59892  }
59893  DUK_ASSERT(rc >= 0);
59894 
59895  if (duk_get_top(ctx) < rc) {
59896  DUK_ERROR_RANGE(thr, "not enough stack values for safe_call rc");
59897  }
59898 
59899  DUK_ASSERT(thr->catchstack_top == entry_catchstack_top); /* no need to unwind */
59900  DUK_ASSERT(thr->callstack_top == entry_callstack_top);
59901 
59902  duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);
59903  return;
59904 
59905  thread_state_error:
59906  DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state for safe_call (%ld)", (long) thr->state);
59907  DUK_UNREACHABLE();
59908 }
59909 
59910 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
59911  duk_idx_t idx_retbase,
59912  duk_idx_t num_stack_rets,
59913  duk_size_t entry_valstack_bottom_index,
59914  duk_size_t entry_callstack_top,
59915  duk_size_t entry_catchstack_top,
59916  duk_jmpbuf *old_jmpbuf_ptr) {
59917  duk_context *ctx;
59918 
59919  DUK_ASSERT(thr != NULL);
59920  ctx = (duk_context *) thr;
59921  DUK_ASSERT_CTX_VALID(ctx);
59922 
59923  /*
59924  * Error during call. The error value is at heap->lj.value1.
59925  *
59926  * The very first thing we do is restore the previous setjmp catcher.
59927  * This means that any error in error handling will propagate outwards
59928  * instead of causing a setjmp() re-entry above.
59929  */
59930 
59931  DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
59932 
59933  /* Other longjmp types are handled by executor before propagating
59934  * the error here.
59935  */
59936  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
59937  DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
59938  DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
59939 
59940  /* Note: either pointer may be NULL (at entry), so don't assert. */
59941  thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
59942 
59943  DUK_ASSERT(thr->catchstack_top >= entry_catchstack_top);
59944  DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
59945  duk_hthread_catchstack_unwind(thr, entry_catchstack_top);
59946  duk_hthread_catchstack_shrink_check(thr);
59947  duk_hthread_callstack_unwind(thr, entry_callstack_top);
59948  duk_hthread_callstack_shrink_check(thr);
59949  thr->valstack_bottom = thr->valstack + entry_valstack_bottom_index;
59950 
59951  /* [ ... | (crud) ] */
59952 
59953  /* XXX: space in valstack? see discussion in duk_handle_call_xxx(). */
59954  duk_push_tval(ctx, &thr->heap->lj.value1);
59955 
59956  /* [ ... | (crud) errobj ] */
59957 
59958  DUK_ASSERT(duk_get_top(ctx) >= 1); /* at least errobj must be on stack */
59959 
59960  /* check that the valstack has space for the final amount and any
59961  * intermediate space needed; this is unoptimal but should be safe
59962  */
59963  duk_require_stack_top(ctx, idx_retbase + num_stack_rets); /* final configuration */
59964  duk_require_stack(ctx, num_stack_rets);
59965 
59966  duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1); /* 1 = num actual 'return values' */
59967 
59968  /* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
59969 
59970  /* These are just convenience "wiping" of state. Side effects should
59971  * not be an issue here: thr->heap and thr->heap->lj have a stable
59972  * pointer. Finalizer runs etc capture even out-of-memory errors so
59973  * nothing should throw here.
59974  */
59975  thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
59976  thr->heap->lj.iserror = 0;
59977  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
59978  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
59979 }
59980 
59981 DUK_LOCAL void duk__handle_safe_call_shared(duk_hthread *thr,
59982  duk_idx_t idx_retbase,
59983  duk_idx_t num_stack_rets,
59984  duk_int_t entry_call_recursion_depth,
59985  duk_hthread *entry_curr_thread,
59986  duk_uint_fast8_t entry_thread_state,
59987  duk_instr_t **entry_ptr_curr_pc) {
59988  duk_context *ctx;
59989 
59990  DUK_ASSERT(thr != NULL);
59991  ctx = (duk_context *) thr;
59992  DUK_ASSERT_CTX_VALID(ctx);
59993  DUK_UNREF(ctx);
59994  DUK_UNREF(idx_retbase);
59995  DUK_UNREF(num_stack_rets);
59996 
59997  /* Restore entry thread executor curr_pc stack frame pointer. */
59998  thr->ptr_curr_pc = entry_ptr_curr_pc;
59999 
60000  /* XXX: because we unwind stacks above, thr->heap->curr_thread is at
60001  * risk of pointing to an already freed thread. This was indeed the
60002  * case in test-bug-multithread-valgrind.c, until duk_handle_call()
60003  * was fixed to restore thr->heap->curr_thread before rethrowing an
60004  * uncaught error.
60005  */
60006  DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread); /* may be NULL */
60007  thr->state = (duk_uint8_t) entry_thread_state;
60008 
60009  DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) || /* first call */
60010  (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) || /* other call */
60011  (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr)); /* current thread */
60012 
60013  thr->heap->call_recursion_depth = entry_call_recursion_depth;
60014 
60015  /* stack discipline consistency check */
60016  DUK_ASSERT(duk_get_top(ctx) == idx_retbase + num_stack_rets);
60017 
60018  /* A debugger forced interrupt check is not needed here, as
60019  * problematic safe calls are not caused by side effects.
60020  */
60021 
60022 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
60023  duk__interrupt_fixup(thr, entry_curr_thread);
60024 #endif
60025 }
60026 
60027 /*
60028  * Helper for handling an Ecmascript-to-Ecmascript call or an Ecmascript
60029  * function (initial) Duktape.Thread.resume().
60030  *
60031  * Compared to normal calls handled by duk_handle_call(), there are a
60032  * bunch of differences:
60033  *
60034  * - the call is never protected
60035  * - there is no C recursion depth increase (hence an "ignore recursion
60036  * limit" flag is not applicable)
60037  * - instead of making the call, this helper just performs the thread
60038  * setup and returns; the bytecode executor then restarts execution
60039  * internally
60040  * - ecmascript functions are never 'vararg' functions (they access
60041  * varargs through the 'arguments' object)
60042  *
60043  * The callstack of the target contains an earlier Ecmascript call in case
60044  * of an Ecmascript-to-Ecmascript call (whose idx_retval is updated), or
60045  * is empty in case of an initial Duktape.Thread.resume().
60046  *
60047  * The first thing to do here is to figure out whether an ecma-to-ecma
60048  * call is actually possible. It's not always the case if the target is
60049  * a bound function; the final function may be native. In that case,
60050  * return an error so caller can fall back to a normal call path.
60051  */
60052 
60053 DUK_INTERNAL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
60054  duk_idx_t num_stack_args,
60055  duk_small_uint_t call_flags) {
60056  duk_context *ctx = (duk_context *) thr;
60057  duk_size_t entry_valstack_bottom_index;
60058  duk_idx_t idx_func; /* valstack index of 'func' and retval (relative to entry valstack_bottom) */
60059  duk_idx_t idx_args; /* valstack index of start of args (arg1) (relative to entry valstack_bottom) */
60060  duk_idx_t nargs; /* # argument registers target function wants (< 0 => never for ecma calls) */
60061  duk_idx_t nregs; /* # total registers target function wants on entry (< 0 => never for ecma calls) */
60062  duk_hobject *func; /* 'func' on stack (borrowed reference) */
60063  duk_tval *tv_func; /* duk_tval ptr for 'func' on stack (borrowed reference) */
60064  duk_activation *act;
60065  duk_hobject *env;
60066  duk_bool_t use_tailcall;
60067  duk_instr_t **entry_ptr_curr_pc;
60068 
60069  DUK_ASSERT(thr != NULL);
60070  DUK_ASSERT(ctx != NULL);
60071  DUK_ASSERT(!((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 && (call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0));
60072 
60073  /* XXX: assume these? */
60074  DUK_ASSERT(thr->valstack != NULL);
60075  DUK_ASSERT(thr->callstack != NULL);
60076  DUK_ASSERT(thr->catchstack != NULL);
60077 
60078  /* no need to handle thread state book-keeping here */
60079  DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ||
60080  (thr->state == DUK_HTHREAD_STATE_RUNNING &&
60081  thr->heap->curr_thread == thr));
60082 
60083  /* If thr->ptr_curr_pc is set, sync curr_pc to act->pc. Then NULL
60084  * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
60085  * activation when side effects occur. If we end up not making the
60086  * call we must restore the value.
60087  */
60088  entry_ptr_curr_pc = thr->ptr_curr_pc;
60089  duk_hthread_sync_and_null_currpc(thr);
60090 
60091  /* if a tail call:
60092  * - an Ecmascript activation must be on top of the callstack
60093  * - there cannot be any active catchstack entries
60094  */
60095 #if defined(DUK_USE_ASSERTIONS)
60096  if (call_flags & DUK_CALL_FLAG_IS_TAILCALL) {
60097  duk_size_t our_callstack_index;
60098  duk_size_t i;
60099 
60100  DUK_ASSERT(thr->callstack_top >= 1);
60101  our_callstack_index = thr->callstack_top - 1;
60102  DUK_ASSERT_DISABLE(our_callstack_index >= 0);
60103  DUK_ASSERT(our_callstack_index < thr->callstack_size);
60104  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index) != NULL);
60105  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + our_callstack_index)));
60106 
60107  /* No entry in the catchstack which would actually catch a
60108  * throw can refer to the callstack entry being reused.
60109  * There *can* be catchstack entries referring to the current
60110  * callstack entry as long as they don't catch (e.g. label sites).
60111  */
60112 
60113  for (i = 0; i < thr->catchstack_top; i++) {
60114  DUK_ASSERT(thr->catchstack[i].callstack_index < our_callstack_index || /* refer to callstack entries below current */
60115  DUK_CAT_GET_TYPE(thr->catchstack + i) == DUK_CAT_TYPE_LABEL); /* or a non-catching entry */
60116  }
60117  }
60118 #endif /* DUK_USE_ASSERTIONS */
60119 
60120  entry_valstack_bottom_index = (duk_size_t) (thr->valstack_bottom - thr->valstack);
60121  /* XXX: rework */
60122  idx_func = duk_normalize_index(thr, -num_stack_args - 2);
60123  idx_args = idx_func + 2;
60124 
60125  DUK_DD(DUK_DDPRINT("handle_ecma_call_setup: thr=%p, "
60126  "num_stack_args=%ld, call_flags=0x%08lx (resume=%ld, tailcall=%ld), "
60127  "idx_func=%ld, idx_args=%ld, entry_valstack_bottom_index=%ld",
60128  (void *) thr,
60129  (long) num_stack_args,
60130  (unsigned long) call_flags,
60131  (long) ((call_flags & DUK_CALL_FLAG_IS_RESUME) != 0 ? 1 : 0),
60132  (long) ((call_flags & DUK_CALL_FLAG_IS_TAILCALL) != 0 ? 1 : 0),
60133  (long) idx_func,
60134  (long) idx_args,
60135  (long) entry_valstack_bottom_index));
60136 
60137  if (DUK_UNLIKELY(idx_func < 0 || idx_args < 0)) {
60138  /* XXX: assert? compiler is responsible for this never happening */
60139  DUK_ERROR_TYPE_INVALID_ARGS(thr);
60140  }
60141 
60142  /*
60143  * Check the function type, handle bound function chains, and prepare
60144  * parameters for the rest of the call handling. Also figure out the
60145  * effective 'this' binding, which replaces the current value at
60146  * idx_func + 1.
60147  *
60148  * If the target function is a 'bound' one, follow the chain of 'bound'
60149  * functions until a non-bound function is found. During this process,
60150  * bound arguments are 'prepended' to existing ones, and the "this"
60151  * binding is overridden. See E5 Section 15.3.4.5.1.
60152  *
60153  * If the final target function cannot be handled by an ecma-to-ecma
60154  * call, return to the caller with a return value indicating this case.
60155  * The bound chain is resolved and the caller can resume with a plain
60156  * function call.
60157  */
60158 
60159  func = duk__nonbound_func_lookup(ctx, idx_func, &num_stack_args, &tv_func, call_flags);
60160  if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
60161  DUK_DDD(DUK_DDDPRINT("final target is a lightfunc/nativefunc, cannot do ecma-to-ecma call"));
60162  thr->ptr_curr_pc = entry_ptr_curr_pc;
60163  return 0;
60164  }
60165  /* XXX: tv_func is not actually needed */
60166 
60167  DUK_ASSERT(func != NULL);
60168  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
60169  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
60170 
60171  duk__coerce_effective_this_binding(thr, func, idx_func + 1);
60172  DUK_DDD(DUK_DDDPRINT("effective 'this' binding is: %!T",
60173  duk_get_tval(ctx, idx_func + 1)));
60174 
60175  nargs = ((duk_hcompfunc *) func)->nargs;
60176  nregs = ((duk_hcompfunc *) func)->nregs;
60177  DUK_ASSERT(nregs >= nargs);
60178 
60179  /* [ ... func this arg1 ... argN ] */
60180 
60181  /*
60182  * Preliminary activation record and valstack manipulation.
60183  * The concrete actions depend on whether the we're dealing
60184  * with a tail call (reuse an existing activation), a resume,
60185  * or a normal call.
60186  *
60187  * The basic actions, in varying order, are:
60188  *
60189  * - Check stack size for call handling
60190  * - Grow call stack if necessary (non-tail-calls)
60191  * - Update current activation (idx_retval) if necessary
60192  * (non-tail, non-resume calls)
60193  * - Move start of args (idx_args) to valstack bottom
60194  * (tail calls)
60195  *
60196  * Don't touch valstack_bottom or valstack_top yet so that Duktape API
60197  * calls work normally.
60198  */
60199 
60200  /* XXX: some overlapping code; cleanup */
60201  use_tailcall = call_flags & DUK_CALL_FLAG_IS_TAILCALL;
60202 #if !defined(DUK_USE_TAILCALL)
60203  DUK_ASSERT(use_tailcall == 0); /* compiler ensures this */
60204 #endif
60205  if (use_tailcall) {
60206  /* tailcall cannot be flagged to resume calls, and a
60207  * previous frame must exist
60208  */
60209  DUK_ASSERT(thr->callstack_top >= 1);
60210  DUK_ASSERT((call_flags & DUK_CALL_FLAG_IS_RESUME) == 0);
60211 
60212  act = thr->callstack + thr->callstack_top - 1;
60213  if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
60214  /* See: test-bug-tailcall-preventyield-assert.c. */
60215  DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENTYIELD"));
60216  use_tailcall = 0;
60217  } else if (DUK_HOBJECT_HAS_NOTAIL(func)) {
60218  DUK_D(DUK_DPRINT("tail call prevented by function having a notail flag"));
60219  use_tailcall = 0;
60220  }
60221  }
60222 
60223  if (use_tailcall) {
60224  duk_tval *tv1, *tv2;
60225  duk_size_t cs_index;
60226  duk_int_t i_stk; /* must be signed for loop structure */
60227  duk_idx_t i_arg;
60228 
60229  /*
60230  * Tailcall handling
60231  *
60232  * Although the callstack entry is reused, we need to explicitly unwind
60233  * the current activation (or simulate an unwind). In particular, the
60234  * current activation must be closed, otherwise something like
60235  * test-bug-reduce-judofyr.js results. Also catchstack needs be unwound
60236  * because there may be non-error-catching label entries in valid tail calls.
60237  */
60238 
60239  DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
60240  (long) (thr->callstack_top - 1)));
60241 
60242  /* 'act' already set above */
60243 
60244  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
60245  DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
60246  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
60247  DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
60248 
60249  /* Unwind catchstack entries referring to the callstack entry we're reusing */
60250  cs_index = thr->callstack_top - 1;
60251  DUK_ASSERT(thr->catchstack_top <= DUK_INT_MAX); /* catchstack limits */
60252  for (i_stk = (duk_int_t) (thr->catchstack_top - 1); i_stk >= 0; i_stk--) {
60253  duk_catcher *cat = thr->catchstack + i_stk;
60254  if (cat->callstack_index != cs_index) {
60255  /* 'i' is the first entry we'll keep */
60256  break;
60257  }
60258  }
60259  duk_hthread_catchstack_unwind(thr, i_stk + 1);
60260 
60261  /* Unwind the topmost callstack entry before reusing it */
60262  DUK_ASSERT(thr->callstack_top > 0);
60263  duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
60264 
60265  /* Then reuse the unwound activation; callstack was not shrunk so there is always space */
60266  thr->callstack_top++;
60267  DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
60268  act = thr->callstack + thr->callstack_top - 1;
60269 
60270  /* Start filling in the activation */
60271  act->func = func; /* don't want an intermediate exposed state with func == NULL */
60272 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
60273  act->prev_caller = NULL;
60274 #endif
60275  DUK_ASSERT(func != NULL);
60276  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
60277  /* don't want an intermediate exposed state with invalid pc */
60278  act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
60279 #if defined(DUK_USE_DEBUGGER_SUPPORT)
60280  act->prev_line = 0;
60281 #endif
60282  DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
60283 #if defined(DUK_USE_REFERENCE_COUNTING)
60284  DUK_HOBJECT_INCREF(thr, func);
60285  act = thr->callstack + thr->callstack_top - 1; /* side effects (currently none though) */
60286 #endif
60287 
60288 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
60289 #if defined(DUK_USE_TAILCALL)
60290 #error incorrect options: tail calls enabled with function caller property
60291 #endif
60292  /* XXX: this doesn't actually work properly for tail calls, so
60293  * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
60294  * is in use.
60295  */
60296  duk__update_func_caller_prop(thr, func);
60297  act = thr->callstack + thr->callstack_top - 1;
60298 #endif
60299 
60300  act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
60301  DUK_ACT_FLAG_STRICT | DUK_ACT_FLAG_TAILCALLED :
60302  DUK_ACT_FLAG_TAILCALLED);
60303 
60304  DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func); /* already updated */
60305  DUK_ASSERT(act->var_env == NULL); /* already NULLed (by unwind) */
60306  DUK_ASSERT(act->lex_env == NULL); /* already NULLed (by unwind) */
60307  act->idx_bottom = entry_valstack_bottom_index; /* tail call -> reuse current "frame" */
60308  DUK_ASSERT(nregs >= 0);
60309 #if 0 /* topmost activation idx_retval is considered garbage, no need to init */
60310  act->idx_retval = 0;
60311 #endif
60312 
60313  /*
60314  * Manipulate valstack so that args are on the current bottom and the
60315  * previous caller's 'this' binding (which is the value preceding the
60316  * current bottom) is replaced with the new 'this' binding:
60317  *
60318  * [ ... this_old | (crud) func this_new arg1 ... argN ]
60319  * --> [ ... this_new | arg1 ... argN ]
60320  *
60321  * For tail calling to work properly, the valstack bottom must not grow
60322  * here; otherwise crud would accumulate on the valstack.
60323  */
60324 
60325  tv1 = thr->valstack_bottom - 1;
60326  tv2 = thr->valstack_bottom + idx_func + 1;
60327  DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top); /* tv1 is -below- valstack_bottom */
60328  DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
60329  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
60330 
60331  for (i_arg = 0; i_arg < idx_args; i_arg++) {
60332  /* XXX: block removal API primitive */
60333  /* Note: 'func' is popped from valstack here, but it is
60334  * already reachable from the activation.
60335  */
60336  duk_remove(ctx, 0);
60337  }
60338  idx_func = 0; DUK_UNREF(idx_func); /* really 'not applicable' anymore, should not be referenced after this */
60339  idx_args = 0;
60340 
60341  /* [ ... this_new | arg1 ... argN ] */
60342  } else {
60343  DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
60344  (long) (thr->callstack_top)));
60345 
60346  duk_hthread_callstack_grow(thr);
60347 
60348  if (call_flags & DUK_CALL_FLAG_IS_RESUME) {
60349  DUK_DDD(DUK_DDDPRINT("is resume -> no update to current activation (may not even exist)"));
60350  } else {
60351  DUK_DDD(DUK_DDDPRINT("update to current activation idx_retval"));
60352  DUK_ASSERT(thr->callstack_top < thr->callstack_size);
60353  DUK_ASSERT(thr->callstack_top >= 1);
60354  act = thr->callstack + thr->callstack_top - 1;
60355  DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
60356  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
60357  act->idx_retval = entry_valstack_bottom_index + idx_func;
60358  }
60359 
60360  DUK_ASSERT(thr->callstack_top < thr->callstack_size);
60361  act = thr->callstack + thr->callstack_top;
60362  thr->callstack_top++;
60363  DUK_ASSERT(thr->callstack_top <= thr->callstack_size);
60364 
60365  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
60366  DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
60367  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
60368 
60369  act->flags = (DUK_HOBJECT_HAS_STRICT(func) ?
60370  DUK_ACT_FLAG_STRICT :
60371  0);
60372  act->func = func;
60373  act->var_env = NULL;
60374  act->lex_env = NULL;
60375 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
60376  act->prev_caller = NULL;
60377 #endif
60378  DUK_ASSERT(func != NULL);
60379  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
60380  act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
60381 #if defined(DUK_USE_DEBUGGER_SUPPORT)
60382  act->prev_line = 0;
60383 #endif
60384  act->idx_bottom = entry_valstack_bottom_index + idx_args;
60385  DUK_ASSERT(nregs >= 0);
60386 #if 0 /* topmost activation idx_retval is considered garbage, no need to init */
60387  act->idx_retval = 0;
60388 #endif
60389  DUK_TVAL_SET_OBJECT(&act->tv_func, func); /* borrowed, no refcount */
60390 
60391  DUK_HOBJECT_INCREF(thr, func); /* act->func */
60392 
60393 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
60394  duk__update_func_caller_prop(thr, func);
60395  act = thr->callstack + thr->callstack_top - 1;
60396 #endif
60397  }
60398 
60399  /* [ ... func this arg1 ... argN ] (not tail call)
60400  * [ this | arg1 ... argN ] (tail call)
60401  *
60402  * idx_args updated to match
60403  */
60404 
60405  /*
60406  * Environment record creation and 'arguments' object creation.
60407  * Named function expression name binding is handled by the
60408  * compiler; the compiled function's parent env will contain
60409  * the (immutable) binding already.
60410  *
60411  * Delayed creation (on demand) is handled in duk_js_var.c.
60412  */
60413 
60414  /* XXX: unify handling with native call. */
60415 
60416  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound function chain has already been resolved */
60417 
60418  if (!DUK_HOBJECT_HAS_NEWENV(func)) {
60419  /* use existing env (e.g. for non-strict eval); cannot have
60420  * an own 'arguments' object (but can refer to the existing one)
60421  */
60422 
60423  duk__handle_oldenv_for_call(thr, func, act);
60424 
60425  DUK_ASSERT(act->lex_env != NULL);
60426  DUK_ASSERT(act->var_env != NULL);
60427  goto env_done;
60428  }
60429 
60430  DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
60431 
60432  if (!DUK_HOBJECT_HAS_CREATEARGS(func)) {
60433  /* no need to create environment record now; leave as NULL */
60434  DUK_ASSERT(act->lex_env == NULL);
60435  DUK_ASSERT(act->var_env == NULL);
60436  goto env_done;
60437  }
60438 
60439  /* third arg: absolute index (to entire valstack) of idx_bottom of new activation */
60440  env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
60441  DUK_ASSERT(env != NULL);
60442 
60443  /* [ ... arg1 ... argN envobj ] */
60444 
60445  /* original input stack before nargs/nregs handling must be
60446  * intact for 'arguments' object
60447  */
60448  DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
60449  duk__handle_createargs_for_call(thr, func, env, num_stack_args);
60450 
60451  /* [ ... arg1 ... argN envobj ] */
60452 
60453  act = thr->callstack + thr->callstack_top - 1;
60454  act->lex_env = env;
60455  act->var_env = env;
60456  DUK_HOBJECT_INCREF(thr, act->lex_env);
60457  DUK_HOBJECT_INCREF(thr, act->var_env);
60458  duk_pop(ctx);
60459 
60460  env_done:
60461  /* [ ... arg1 ... argN ] */
60462 
60463  /*
60464  * Setup value stack: clamp to 'nargs', fill up to 'nregs'
60465  */
60466 
60467  duk__adjust_valstack_and_top(thr,
60468  num_stack_args,
60469  idx_args,
60470  nregs,
60471  nargs,
60472  func);
60473 
60474  /*
60475  * Shift to new valstack_bottom.
60476  */
60477 
60478  thr->valstack_bottom = thr->valstack_bottom + idx_args;
60479  /* keep current valstack_top */
60480  DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
60481  DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
60482  DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
60483 
60484  /*
60485  * Return to bytecode executor, which will resume execution from
60486  * the topmost activation.
60487  */
60488 
60489  return 1;
60490 }
60491 /*
60492  * Ecmascript compiler.
60493  *
60494  * Parses an input string and generates a function template result.
60495  * Compilation may happen in multiple contexts (global code, eval
60496  * code, function code).
60497  *
60498  * The parser uses a traditional top-down recursive parsing for the
60499  * statement level, and an operator precedence based top-down approach
60500  * for the expression level. The attempt is to minimize the C stack
60501  * depth. Bytecode is generated directly without an intermediate
60502  * representation (tree), at the cost of needing two (and sometimes
60503  * three) passes over each function.
60504  *
60505  * The top-down recursive parser functions are named "duk__parse_XXX".
60506  *
60507  * Recursion limits are in key functions to prevent arbitrary C recursion:
60508  * function body parsing, statement parsing, and expression parsing.
60509  *
60510  * See doc/compiler.rst for discussion on the design.
60511  *
60512  * A few typing notes:
60513  *
60514  * - duk_regconst_t: unsigned, no marker value for "none"
60515  * - duk_reg_t: signed, < 0 = none
60516  * - PC values: duk_int_t, negative values used as markers
60517  */
60518 
60519 /* #include duk_internal.h -> already included */
60520 
60521 /* If highest bit of a register number is set, it refers to a constant instead.
60522  * When interpreted as a signed value, this means const values are always
60523  * negative (when interpreted as two's complement). For example DUK__ISTEMP()
60524  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
60525  * logically "'x' is a register AND 'x' >= temp_first").
60526  */
60527 #define DUK__CONST_MARKER DUK_REGCONST_CONST_MARKER
60528 #define DUK__ISREG(x) (((x) & DUK__CONST_MARKER) == 0)
60529 #define DUK__ISCONST(x) (((x) & DUK__CONST_MARKER) != 0)
60530 #define DUK__REMOVECONST(x) ((x) & ~DUK__CONST_MARKER)
60531 #define DUK__ISTEMP(comp_ctx,x) ((duk_int32_t) (x) >= (duk_int32_t) ((comp_ctx)->curr_func.temp_first)) /* Avoid DUK__ISREG() check by interpreting as negative value. */
60532 #define DUK__GETTEMP(comp_ctx) ((comp_ctx)->curr_func.temp_next)
60533 #define DUK__SETTEMP(comp_ctx,x) ((comp_ctx)->curr_func.temp_next = (x)) /* dangerous: must only lower (temp_max not updated) */
60534 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x) duk__settemp_checkmax((comp_ctx),(x))
60535 #define DUK__ALLOCTEMP(comp_ctx) duk__alloctemp((comp_ctx))
60536 #define DUK__ALLOCTEMPS(comp_ctx,count) duk__alloctemps((comp_ctx),(count))
60537 
60538 /* Init value set size for array and object literals. */
60539 #define DUK__MAX_ARRAY_INIT_VALUES 20
60540 #define DUK__MAX_OBJECT_INIT_PAIRS 10
60541 
60542 /* XXX: hack, remove when const lookup is not O(n) */
60543 #define DUK__GETCONST_MAX_CONSTS_CHECK 256
60544 
60545 /* These limits are based on bytecode limits. Max temps is limited
60546  * by duk_hcompfunc nargs/nregs fields being 16 bits.
60547  */
60548 #define DUK__MAX_CONSTS DUK_BC_BC_MAX
60549 #define DUK__MAX_FUNCS DUK_BC_BC_MAX
60550 #define DUK__MAX_TEMPS 0xffffL
60551 
60552 /* Initial bytecode size allocation. */
60553 #if defined(DUK_USE_PREFER_SIZE)
60554 #define DUK__BC_INITIAL_INSTS 16
60555 #else
60556 #define DUK__BC_INITIAL_INSTS 256
60557 #endif
60558 
60559 #define DUK__RECURSION_INCREASE(comp_ctx,thr) do { \
60560  DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
60561  duk__recursion_increase((comp_ctx)); \
60562  } while (0)
60563 
60564 #define DUK__RECURSION_DECREASE(comp_ctx,thr) do { \
60565  DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
60566  duk__recursion_decrease((comp_ctx)); \
60567  } while (0)
60568 
60569 /* Value stack slot limits: these are quite approximate right now, and
60570  * because they overlap in control flow, some could be eliminated.
60571  */
60572 #define DUK__COMPILE_ENTRY_SLOTS 8
60573 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS 16
60574 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS 16
60575 #define DUK__PARSE_STATEMENTS_SLOTS 16
60576 #define DUK__PARSE_EXPR_SLOTS 16
60577 
60578 /* Temporary structure used to pass a stack allocated region through
60579  * duk_safe_call().
60580  */
60581 typedef struct {
60582  duk_small_uint_t flags;
60583  duk_compiler_ctx comp_ctx_alloc;
60584  duk_lexer_point lex_pt_alloc;
60586 
60587 /*
60588  * Prototypes
60589  */
60590 
60591 /* lexing */
60592 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
60593 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
60594 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
60595 
60596 /* function helpers */
60597 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
60598 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
60599 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg);
60600 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
60601 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
60602 
60603 /* code emission */
60604 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
60605 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
60606 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
60607 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
60608 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);
60609 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);
60610 DUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c);
60611 #if 0 /* unused */
60612 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
60613 #endif
60614 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
60615 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);
60616 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
60617 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
60618 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
60619 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val);
60620 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
60621 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
60622 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
60623 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
60624 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
60625 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);
60626 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
60627 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
60628 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
60629 
60630 /* ivalue/ispec helpers */
60631 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
60632 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60633 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60634 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
60635 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
60636 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
60637 DUK_LOCAL_DECL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
60638 DUK_LOCAL_DECL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
60639 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next);
60640 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
60641 DUK_LOCAL_DECL
60642 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
60643  duk_ispec *x,
60644  duk_reg_t forced_reg,
60645  duk_small_uint_t flags);
60646 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg);
60647 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg);
60648 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60649 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60650 DUK_LOCAL_DECL
60651 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
60652  duk_ivalue *x,
60653  duk_reg_t forced_reg,
60654  duk_small_uint_t flags);
60655 DUK_LOCAL_DECL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60656 #if 0 /* unused */
60657 DUK_LOCAL_DECL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60658 #endif
60659 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
60660 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60661 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
60662 
60663 /* identifier handling */
60664 DUK_LOCAL_DECL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
60665 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);
60666 
60667 /* label handling */
60668 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);
60669 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
60670 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);
60671 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len);
60672 
60673 /* top-down expression parser */
60674 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60675 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
60676 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
60677 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
60678 
60679 /* exprtop is the top level variant which resets nud/led counts */
60680 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60681 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60682 
60683 /* convenience helpers */
60684 #if 0 /* unused */
60685 DUK_LOCAL_DECL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60686 #endif
60687 #if 0 /* unused */
60688 DUK_LOCAL_DECL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60689 #endif
60690 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);
60691 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60692 #if 0 /* unused */
60693 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60694 #endif
60695 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60696 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60697 DUK_LOCAL_DECL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60698 #if 0 /* unused */
60699 DUK_LOCAL_DECL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60700 #endif
60701 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);
60702 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60703 #if 0 /* unused */
60704 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
60705 #endif
60706 
60707 /* expression parsing helpers */
60708 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60709 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60710 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60711 
60712 /* statement parsing */
60713 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);
60714 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
60715 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
60716 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
60717 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60718 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
60719 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
60720 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60721 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60722 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60723 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60724 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
60725 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
60726 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
60727 DUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);
60728 
60729 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);
60730 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
60731 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
60732 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
60733 
60734 #define DUK__FUNC_FLAG_DECL (1 << 0) /* Parsing a function declaration. */
60735 #define DUK__FUNC_FLAG_GETSET (1 << 1) /* Parsing an object literal getter/setter. */
60736 #define DUK__FUNC_FLAG_METDEF (1 << 2) /* Parsing an object literal method definition shorthand. */
60737 #define DUK__FUNC_FLAG_PUSHNAME_PASS1 (1 << 3) /* Push function name when creating template (first pass only). */
60738 #define DUK__FUNC_FLAG_USE_PREVTOKEN (1 << 4) /* Use prev_token to start function parsing (workaround for object literal). */
60739 
60740 /*
60741  * Parser control values for tokens. The token table is ordered by the
60742  * DUK_TOK_XXX defines.
60743  *
60744  * The binding powers are for lbp() use (i.e. for use in led() context).
60745  * Binding powers are positive for typing convenience, and bits at the
60746  * top should be reserved for flags. Binding power step must be higher
60747  * than 1 so that binding power "lbp - 1" can be used for right associative
60748  * operators. Currently a step of 2 is used (which frees one more bit for
60749  * flags).
60750  */
60751 
60752 /* XXX: actually single step levels would work just fine, clean up */
60753 
60754 /* binding power "levels" (see doc/compiler.rst) */
60755 #define DUK__BP_INVALID 0 /* always terminates led() */
60756 #define DUK__BP_EOF 2
60757 #define DUK__BP_CLOSING 4 /* token closes expression, e.g. ')', ']' */
60758 #define DUK__BP_FOR_EXPR DUK__BP_CLOSING /* bp to use when parsing a top level Expression */
60759 #define DUK__BP_COMMA 6
60760 #define DUK__BP_ASSIGNMENT 8
60761 #define DUK__BP_CONDITIONAL 10
60762 #define DUK__BP_LOR 12
60763 #define DUK__BP_LAND 14
60764 #define DUK__BP_BOR 16
60765 #define DUK__BP_BXOR 18
60766 #define DUK__BP_BAND 20
60767 #define DUK__BP_EQUALITY 22
60768 #define DUK__BP_RELATIONAL 24
60769 #define DUK__BP_SHIFT 26
60770 #define DUK__BP_ADDITIVE 28
60771 #define DUK__BP_MULTIPLICATIVE 30
60772 #define DUK__BP_EXPONENTIATION 32
60773 #define DUK__BP_POSTFIX 34
60774 #define DUK__BP_CALL 36
60775 #define DUK__BP_MEMBER 38
60776 
60777 #define DUK__TOKEN_LBP_BP_MASK 0x1f
60778 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP (1 << 5) /* regexp literal must not follow this token */
60779 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6) /* terminates expression; e.g. post-increment/-decrement */
60780 #define DUK__TOKEN_LBP_FLAG_UNUSED (1 << 7) /* spare */
60781 
60782 #define DUK__TOKEN_LBP_GET_BP(x) ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
60783 
60784 #define DUK__MK_LBP(bp) ((bp) >> 1) /* bp is assumed to be even */
60785 #define DUK__MK_LBP_FLAGS(bp,flags) (((bp) >> 1) | (flags))
60786 
60787 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
60788  DUK__MK_LBP(DUK__BP_EOF), /* DUK_TOK_EOF */
60789  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_IDENTIFIER */
60790  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BREAK */
60791  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CASE */
60792  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CATCH */
60793  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONTINUE */
60794  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEBUGGER */
60795  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DEFAULT */
60796  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DELETE */
60797  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_DO */
60798  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ELSE */
60799  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FINALLY */
60800  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FOR */
60801  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_FUNCTION */
60802  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IF */
60803  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_IN */
60804  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_INSTANCEOF */
60805  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_NEW */
60806  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_RETURN */
60807  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SWITCH */
60808  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_THIS */
60809  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_THROW */
60810  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TRY */
60811  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_TYPEOF */
60812  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VAR */
60813  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CONST */
60814  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_VOID */
60815  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WHILE */
60816  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_WITH */
60817  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_CLASS */
60818  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_ENUM */
60819  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXPORT */
60820  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_EXTENDS */
60821  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPORT */
60822  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SUPER */
60823  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NULL */
60824  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_TRUE */
60825  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_FALSE */
60826  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_GET */
60827  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SET */
60828  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_IMPLEMENTS */
60829  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_INTERFACE */
60830  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LET */
60831  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PACKAGE */
60832  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PRIVATE */
60833  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PROTECTED */
60834  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_PUBLIC */
60835  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_STATIC */
60836  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_YIELD */
60837  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LCURLY */
60838  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RCURLY */
60839  DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_LBRACKET */
60840  DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RBRACKET */
60841  DUK__MK_LBP(DUK__BP_CALL), /* DUK_TOK_LPAREN */
60842  DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_RPAREN */
60843  DUK__MK_LBP(DUK__BP_MEMBER), /* DUK_TOK_PERIOD */
60844  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_SEMICOLON */
60845  DUK__MK_LBP(DUK__BP_COMMA), /* DUK_TOK_COMMA */
60846  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LT */
60847  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GT */
60848  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_LE */
60849  DUK__MK_LBP(DUK__BP_RELATIONAL), /* DUK_TOK_GE */
60850  DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_EQ */
60851  DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_NEQ */
60852  DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SEQ */
60853  DUK__MK_LBP(DUK__BP_EQUALITY), /* DUK_TOK_SNEQ */
60854  DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_ADD */
60855  DUK__MK_LBP(DUK__BP_ADDITIVE), /* DUK_TOK_SUB */
60856  DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MUL */
60857  DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_DIV */
60858  DUK__MK_LBP(DUK__BP_MULTIPLICATIVE), /* DUK_TOK_MOD */
60859  DUK__MK_LBP(DUK__BP_EXPONENTIATION), /* DUK_TOK_EXP */
60860  DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_INCREMENT */
60861  DUK__MK_LBP(DUK__BP_POSTFIX), /* DUK_TOK_DECREMENT */
60862  DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ALSHIFT */
60863  DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_ARSHIFT */
60864  DUK__MK_LBP(DUK__BP_SHIFT), /* DUK_TOK_RSHIFT */
60865  DUK__MK_LBP(DUK__BP_BAND), /* DUK_TOK_BAND */
60866  DUK__MK_LBP(DUK__BP_BOR), /* DUK_TOK_BOR */
60867  DUK__MK_LBP(DUK__BP_BXOR), /* DUK_TOK_BXOR */
60868  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_LNOT */
60869  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_BNOT */
60870  DUK__MK_LBP(DUK__BP_LAND), /* DUK_TOK_LAND */
60871  DUK__MK_LBP(DUK__BP_LOR), /* DUK_TOK_LOR */
60872  DUK__MK_LBP(DUK__BP_CONDITIONAL), /* DUK_TOK_QUESTION */
60873  DUK__MK_LBP(DUK__BP_INVALID), /* DUK_TOK_COLON */
60874  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EQUALSIGN */
60875  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ADD_EQ */
60876  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_SUB_EQ */
60877  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MUL_EQ */
60878  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_DIV_EQ */
60879  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_MOD_EQ */
60880  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_EXP_EQ */
60881  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ALSHIFT_EQ */
60882  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_ARSHIFT_EQ */
60883  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_RSHIFT_EQ */
60884  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BAND_EQ */
60885  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BOR_EQ */
60886  DUK__MK_LBP(DUK__BP_ASSIGNMENT), /* DUK_TOK_BXOR_EQ */
60887  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_NUMBER */
60888  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_STRING */
60889  DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP), /* DUK_TOK_REGEXP */
60890 };
60891 
60892 /*
60893  * Misc helpers
60894  */
60895 
60896 DUK_LOCAL void duk__recursion_increase(duk_compiler_ctx *comp_ctx) {
60897  DUK_ASSERT(comp_ctx != NULL);
60898  DUK_ASSERT(comp_ctx->recursion_depth >= 0);
60899  if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
60900  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
60901  }
60902  comp_ctx->recursion_depth++;
60903 }
60904 
60905 DUK_LOCAL void duk__recursion_decrease(duk_compiler_ctx *comp_ctx) {
60906  DUK_ASSERT(comp_ctx != NULL);
60907  DUK_ASSERT(comp_ctx->recursion_depth > 0);
60908  comp_ctx->recursion_depth--;
60909 }
60910 
60911 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
60912  DUK_UNREF(comp_ctx);
60913  DUK_ASSERT(h != NULL);
60914  return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
60915 }
60916 
60917 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
60918  DUK_ASSERT(h != NULL);
60919  return (comp_ctx->curr_func.is_strict &&
60920  DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
60921 }
60922 
60923 /*
60924  * Parser duk__advance() token eating functions
60925  */
60926 
60927 /* XXX: valstack handling is awkward. Add a valstack helper which
60928  * avoids dup():ing; valstack_copy(src, dst)?
60929  */
60930 
60931 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
60932  duk_hthread *thr = comp_ctx->thr;
60933  duk_context *ctx = (duk_context *) thr;
60934  duk_bool_t regexp;
60935 
60936  DUK_ASSERT(comp_ctx->curr_token.t >= 0 && comp_ctx->curr_token.t <= DUK_TOK_MAXVAL); /* MAXVAL is inclusive */
60937 
60938  /*
60939  * Use current token to decide whether a RegExp can follow.
60940  *
60941  * We can use either 't' or 't_nores'; the latter would not
60942  * recognize keywords. Some keywords can be followed by a
60943  * RegExp (e.g. "return"), so using 't' is better. This is
60944  * not trivial, see doc/compiler.rst.
60945  */
60946 
60947  regexp = 1;
60948  if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
60949  regexp = 0;
60950  }
60951  if (comp_ctx->curr_func.reject_regexp_in_adv) {
60952  comp_ctx->curr_func.reject_regexp_in_adv = 0;
60953  regexp = 0;
60954  }
60955 
60956  if (expect >= 0 && comp_ctx->curr_token.t != expect) {
60957  DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
60958  (long) expect, (long) comp_ctx->curr_token.t));
60959  DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
60960  }
60961 
60962  /* make current token the previous; need to fiddle with valstack "backing store" */
60963  DUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
60964  duk_copy(ctx, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
60965  duk_copy(ctx, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
60966 
60967  /* parse new token */
60968  duk_lexer_parse_js_input_element(&comp_ctx->lex,
60969  &comp_ctx->curr_token,
60970  comp_ctx->curr_func.is_strict,
60971  regexp);
60972 
60973  DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
60974  "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
60975  (long) comp_ctx->curr_token.t,
60976  (long) comp_ctx->curr_token.t_nores,
60977  (long) comp_ctx->curr_token.start_line,
60978  (long) comp_ctx->curr_token.lineterm,
60979  (duk_tval *) duk_get_tval(ctx, comp_ctx->tok11_idx),
60980  (duk_tval *) duk_get_tval(ctx, comp_ctx->tok12_idx),
60981  (long) comp_ctx->prev_token.t,
60982  (long) comp_ctx->prev_token.t_nores,
60983  (long) comp_ctx->prev_token.start_line,
60984  (long) comp_ctx->prev_token.lineterm,
60985  (duk_tval *) duk_get_tval(ctx, comp_ctx->tok21_idx),
60986  (duk_tval *) duk_get_tval(ctx, comp_ctx->tok22_idx)));
60987 }
60988 
60989 /* advance, expecting current token to be a specific token; parse next token in regexp context */
60990 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
60991  duk__advance_helper(comp_ctx, expect);
60992 }
60993 
60994 /* advance, whatever the current token is; parse next token in regexp context */
60995 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
60996  duk__advance_helper(comp_ctx, -1);
60997 }
60998 
60999 /*
61000  * Helpers for duk_compiler_func.
61001  */
61002 
61003 /* init function state: inits valstack allocations */
61004 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
61005  duk_compiler_func *func = &comp_ctx->curr_func;
61006  duk_hthread *thr = comp_ctx->thr;
61007  duk_context *ctx = (duk_context *) thr;
61008  duk_idx_t entry_top;
61009 
61010  entry_top = duk_get_top(ctx);
61011 
61012  DUK_MEMZERO(func, sizeof(*func)); /* intentional overlap with earlier memzero */
61013 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
61014  func->h_name = NULL;
61015  func->h_consts = NULL;
61016  func->h_funcs = NULL;
61017  func->h_decls = NULL;
61018  func->h_labelnames = NULL;
61019  func->h_labelinfos = NULL;
61020  func->h_argnames = NULL;
61021  func->h_varmap = NULL;
61022 #endif
61023 
61024  duk_require_stack(ctx, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
61025 
61026  DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
61027  /* code_idx = entry_top + 0 */
61028 
61029  duk_push_array(ctx);
61030  func->consts_idx = entry_top + 1;
61031  func->h_consts = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 1);
61032  DUK_ASSERT(func->h_consts != NULL);
61033 
61034  duk_push_array(ctx);
61035  func->funcs_idx = entry_top + 2;
61036  func->h_funcs = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 2);
61037  DUK_ASSERT(func->h_funcs != NULL);
61038  DUK_ASSERT(func->fnum_next == 0);
61039 
61040  duk_push_array(ctx);
61041  func->decls_idx = entry_top + 3;
61042  func->h_decls = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 3);
61043  DUK_ASSERT(func->h_decls != NULL);
61044 
61045  duk_push_array(ctx);
61046  func->labelnames_idx = entry_top + 4;
61047  func->h_labelnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 4);
61048  DUK_ASSERT(func->h_labelnames != NULL);
61049 
61050  duk_push_dynamic_buffer(ctx, 0);
61051  func->labelinfos_idx = entry_top + 5;
61052  func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(ctx, entry_top + 5);
61053  DUK_ASSERT(func->h_labelinfos != NULL);
61054  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
61055 
61056  duk_push_array(ctx);
61057  func->argnames_idx = entry_top + 6;
61058  func->h_argnames = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 6);
61059  DUK_ASSERT(func->h_argnames != NULL);
61060 
61061  duk_push_bare_object(ctx);
61062  func->varmap_idx = entry_top + 7;
61063  func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, entry_top + 7);
61064  DUK_ASSERT(func->h_varmap != NULL);
61065 }
61066 
61067 /* reset function state (prepare for pass 2) */
61068 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
61069  duk_compiler_func *func = &comp_ctx->curr_func;
61070  duk_hthread *thr = comp_ctx->thr;
61071  duk_context *ctx = (duk_context *) thr;
61072 
61073  /* reset bytecode buffer but keep current size; pass 2 will
61074  * require same amount or more.
61075  */
61076  DUK_BW_RESET_SIZE(thr, &func->bw_code);
61077 
61078  duk_set_length(ctx, func->consts_idx, 0);
61079  /* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
61080  func->fnum_next = 0;
61081  /* duk_set_length(ctx, func->funcs_idx, 0); */
61082  duk_set_length(ctx, func->labelnames_idx, 0);
61083  duk_hbuffer_reset(thr, func->h_labelinfos);
61084  /* keep func->h_argnames; it is fixed for all passes */
61085 
61086  /* truncated in case pass 3 needed */
61087  duk_push_bare_object(ctx);
61088  duk_replace(ctx, func->varmap_idx);
61089  func->h_varmap = DUK_GET_HOBJECT_POSIDX(ctx, func->varmap_idx);
61090  DUK_ASSERT(func->h_varmap != NULL);
61091 }
61092 
61093 /* cleanup varmap from any null entries, compact it, etc; returns number
61094  * of final entries after cleanup.
61095  */
61096 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
61097  duk_hthread *thr = comp_ctx->thr;
61098  duk_context *ctx = (duk_context *) thr;
61099  duk_hobject *h_varmap;
61100  duk_hstring *h_key;
61101  duk_tval *tv;
61102  duk_uint32_t i, e_next;
61103  duk_int_t ret;
61104 
61105  /* [ ... varmap ] */
61106 
61107  h_varmap = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
61108  DUK_ASSERT(h_varmap != NULL);
61109 
61110  ret = 0;
61111  e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
61112  for (i = 0; i < e_next; i++) {
61113  h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
61114  if (!h_key) {
61115  continue;
61116  }
61117 
61118  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
61119 
61120  /* The entries can either be register numbers or 'null' values.
61121  * Thus, no need to DECREF them and get side effects. DECREF'ing
61122  * the keys (strings) can cause memory to be freed but no side
61123  * effects as strings don't have finalizers. This is why we can
61124  * rely on the object properties not changing from underneath us.
61125  */
61126 
61127  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
61128  if (!DUK_TVAL_IS_NUMBER(tv)) {
61129  DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
61130  DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
61131  DUK_HSTRING_DECREF(thr, h_key);
61132  /* when key is NULL, value is garbage so no need to set */
61133  } else {
61134  ret++;
61135  }
61136  }
61137 
61138  duk_compact_m1(ctx);
61139 
61140  return ret;
61141 }
61142 
61143 /* Convert duk_compiler_func into a function template, leaving the result
61144  * on top of stack.
61145  */
61146 /* XXX: awkward and bloated asm -- use faster internal accesses */
61147 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
61148  duk_compiler_func *func = &comp_ctx->curr_func;
61149  duk_hthread *thr = comp_ctx->thr;
61150  duk_context *ctx = (duk_context *) thr;
61151  duk_hcompfunc *h_res;
61152  duk_hbuffer_fixed *h_data;
61153  duk_size_t consts_count;
61154  duk_size_t funcs_count;
61155  duk_size_t code_count;
61156  duk_size_t code_size;
61157  duk_size_t data_size;
61158  duk_size_t i;
61159  duk_tval *p_const;
61160  duk_hobject **p_func;
61161  duk_instr_t *p_instr;
61162  duk_compiler_instr *q_instr;
61163  duk_tval *tv;
61164  duk_bool_t keep_varmap;
61165  duk_bool_t keep_formals;
61166 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
61167  duk_size_t formals_length;
61168 #endif
61169 
61170  DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
61171 
61172  /*
61173  * Push result object and init its flags
61174  */
61175 
61176  /* Valstack should suffice here, required on function valstack init */
61177 
61178  h_res = duk_push_hcompfunc(ctx);
61179  DUK_ASSERT(h_res != NULL);
61180  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
61181  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL); /* Function templates are "bare objects". */
61182 
61183  if (func->is_function) {
61184  DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
61185  DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
61186 
61187  if (!func->is_arguments_shadowed) {
61188  /* arguments object would be accessible; note that shadowing
61189  * bindings are arguments or function declarations, neither
61190  * of which are deletable, so this is safe.
61191  */
61192 
61193  if (func->id_access_arguments || func->may_direct_eval) {
61194  DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
61195  "indirectly -> set CREATEARGS"));
61196  DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
61197  }
61198  }
61199  } else if (func->is_eval && func->is_strict) {
61200  DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
61201  DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
61202  } else {
61203  /* non-strict eval: env is caller's env or global env (direct vs. indirect call)
61204  * global code: env is is global env
61205  */
61206  DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
61207  DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
61208  }
61209 
61210 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
61211  if (func->is_function && func->is_namebinding && func->h_name != NULL) {
61212  /* Object literal set/get functions have a name (property
61213  * name) but must not have a lexical name binding, see
61214  * test-bug-getset-func-name.js.
61215  */
61216  DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
61217  DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
61218  }
61219 #endif
61220 
61221  if (func->is_strict) {
61222  DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
61223  DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
61224  }
61225 
61226  if (func->is_notail) {
61227  DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
61228  DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
61229  }
61230 
61231  if (func->is_constructable) {
61232  DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
61233  DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
61234  }
61235 
61236  /*
61237  * Build function fixed size 'data' buffer, which contains bytecode,
61238  * constants, and inner function references.
61239  *
61240  * During the building phase 'data' is reachable but incomplete.
61241  * Only incref's occur during building (no refzero or GC happens),
61242  * so the building process is atomic.
61243  */
61244 
61245  consts_count = duk_hobject_get_length(thr, func->h_consts);
61246  funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
61247  code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
61248  code_size = code_count * sizeof(duk_instr_t);
61249 
61250  data_size = consts_count * sizeof(duk_tval) +
61251  funcs_count * sizeof(duk_hobject *) +
61252  code_size;
61253 
61254  DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
61255  "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
61256  (long) consts_count, (long) funcs_count, (long) code_size,
61257  (long) consts_count, (long) sizeof(duk_tval),
61258  (long) funcs_count, (long) sizeof(duk_hobject *),
61259  (long) code_size, (long) data_size));
61260 
61261  duk_push_fixed_buffer_nozero(ctx, data_size);
61262  h_data = (duk_hbuffer_fixed *) duk_known_hbuffer(ctx, -1);
61263 
61264  DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
61265  DUK_HEAPHDR_INCREF(thr, h_data);
61266 
61267  p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
61268  for (i = 0; i < consts_count; i++) {
61269  DUK_ASSERT(i <= DUK_UARRIDX_MAX); /* const limits */
61270  tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
61271  DUK_ASSERT(tv != NULL);
61272  DUK_TVAL_SET_TVAL(p_const, tv);
61273  p_const++;
61274  DUK_TVAL_INCREF(thr, tv); /* may be a string constant */
61275 
61276  DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
61277  }
61278 
61279  p_func = (duk_hobject **) p_const;
61280  DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
61281  for (i = 0; i < funcs_count; i++) {
61282  duk_hobject *h;
61283  DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX); /* func limits */
61284  tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
61285  DUK_ASSERT(tv != NULL);
61286  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
61287  h = DUK_TVAL_GET_OBJECT(tv);
61288  DUK_ASSERT(h != NULL);
61289  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
61290  *p_func++ = h;
61291  DUK_HOBJECT_INCREF(thr, h);
61292 
61293  DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
61294  (void *) h, (duk_heaphdr *) h));
61295  }
61296 
61297  p_instr = (duk_instr_t *) p_func;
61298  DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
61299 
61300  /* copy bytecode instructions one at a time */
61301  q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
61302  for (i = 0; i < code_count; i++) {
61303  p_instr[i] = q_instr[i].ins;
61304  }
61305  /* Note: 'q_instr' is still used below */
61306 
61307  DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
61308 
61309  duk_pop(ctx); /* 'data' (and everything in it) is reachable through h_res now */
61310 
61311  /*
61312  * Init non-property result fields
61313  *
61314  * 'nregs' controls how large a register frame is allocated.
61315  *
61316  * 'nargs' controls how many formal arguments are written to registers:
61317  * r0, ... r(nargs-1). The remaining registers are initialized to
61318  * undefined.
61319  */
61320 
61321  DUK_ASSERT(func->temp_max >= 0);
61322  h_res->nregs = (duk_uint16_t) func->temp_max;
61323  h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
61324  DUK_ASSERT(h_res->nregs >= h_res->nargs); /* pass2 allocation handles this */
61325 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61326  h_res->start_line = (duk_uint32_t) func->min_line;
61327  h_res->end_line = (duk_uint32_t) func->max_line;
61328 #endif
61329 
61330  /*
61331  * Init object properties
61332  *
61333  * Properties should be added in decreasing order of access frequency.
61334  * (Not very critical for function templates.)
61335  */
61336 
61337  DUK_DDD(DUK_DDDPRINT("init function properties"));
61338 
61339  /* [ ... res ] */
61340 
61341  /* _Varmap: omitted if function is guaranteed not to do a slow path
61342  * identifier access that might be caught by locally declared variables.
61343  * The varmap can also be omitted if it turns out empty of actual
61344  * register mappings after a cleanup. When debugging is enabled, we
61345  * always need the varmap to be able to lookup variables at any point.
61346  */
61347 
61348 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61349  DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
61350  keep_varmap = 1;
61351 #else
61352  if (func->id_access_slow_own || /* directly uses slow accesses that may match own variables */
61353  func->id_access_arguments || /* accesses 'arguments' directly */
61354  func->may_direct_eval || /* may indirectly slow access through a direct eval */
61355  funcs_count > 0) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
61356  DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
61357  keep_varmap = 1;
61358  } else {
61359  DUK_DD(DUK_DDPRINT("dropping _Varmap"));
61360  keep_varmap = 0;
61361  }
61362 #endif
61363 
61364  if (keep_varmap) {
61365  duk_int_t num_used;
61366  duk_dup(ctx, func->varmap_idx);
61367  num_used = duk__cleanup_varmap(comp_ctx);
61368  DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
61369  (duk_tval *) duk_get_tval(ctx, -1), (long) num_used));
61370 
61371  if (num_used > 0) {
61372  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
61373  } else {
61374  DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
61375  duk_pop(ctx);
61376  }
61377  }
61378 
61379  /* _Formals: omitted if function is guaranteed not to need a (non-strict)
61380  * arguments object, and _Formals.length matches nargs exactly.
61381  *
61382  * Non-arrow functions can't see an outer function's 'argument' binding
61383  * (because they have their own), but arrow functions can. When arrow
61384  * functions are added, this condition would need to be added:
61385  * inner_arrow_funcs_count > 0 inner arrow functions may access 'arguments'
61386  */
61387 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61388  DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
61389  keep_formals = 1;
61390 #else
61391  formals_length = duk_get_length(ctx, func->argnames_idx);
61392  if (formals_length != (duk_size_t) h_res->nargs) {
61393  /* Nargs not enough for closure .length: keep _Formals regardless
61394  * of its length. Shouldn't happen in practice at the moment.
61395  */
61396  DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
61397  keep_formals = 1;
61398  } else if ((func->id_access_arguments || func->may_direct_eval) &&
61399  (formals_length > 0)) {
61400  /* Direct eval (may access 'arguments') or accesses 'arguments'
61401  * explicitly: keep _Formals unless it is zero length.
61402  */
61403  DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
61404  keep_formals = 1;
61405  } else {
61406  DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
61407  keep_formals = 0;
61408  }
61409 #endif
61410 
61411  if (keep_formals) {
61412  duk_dup(ctx, func->argnames_idx);
61413  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
61414  }
61415 
61416  /* name */
61417 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
61418  if (func->h_name) {
61419  duk_push_hstring(ctx, func->h_name);
61420  DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(ctx, -1)));
61421  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
61422  }
61423 #endif /* DUK_USE_FUNC_NAME_PROPERTY */
61424 
61425  /* _Source */
61426 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
61427  if (0) {
61428  /* XXX: Currently function source code is not stored, as it is not
61429  * required by the standard. Source code should not be stored by
61430  * default (user should enable it explicitly), and the source should
61431  * probably be compressed with a trivial text compressor; average
61432  * compression of 20-30% is quite easy to achieve even with a trivial
61433  * compressor (RLE + backwards lookup).
61434  *
61435  * Debugging needs source code to be useful: sometimes input code is
61436  * not found in files as it may be generated and then eval()'d, given
61437  * by dynamic C code, etc.
61438  *
61439  * Other issues:
61440  *
61441  * - Need tokenizer indices for start and end to substring
61442  * - Always normalize function declaration part?
61443  * - If we keep _Formals, only need to store body
61444  */
61445 
61446  /*
61447  * For global or eval code this is straightforward. For functions
61448  * created with the Function constructor we only get the source for
61449  * the body and must manufacture the "function ..." part.
61450  *
61451  * For instance, for constructed functions (v8):
61452  *
61453  * > a = new Function("foo", "bar", "print(foo)");
61454  * [Function]
61455  * > a.toString()
61456  * 'function anonymous(foo,bar) {\nprint(foo)\n}'
61457  *
61458  * Similarly for e.g. getters (v8):
61459  *
61460  * > x = { get a(foo,bar) { print(foo); } }
61461  * { a: [Getter] }
61462  * > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
61463  * 'function a(foo,bar) { print(foo); }'
61464  */
61465 
61466 #if 0
61467  duk_push_string(ctx, "XXX");
61468  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
61469 #endif
61470  }
61471 #endif /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
61472 
61473  /* _Pc2line */
61474 #if defined(DUK_USE_PC2LINE)
61475  if (1) {
61476  /*
61477  * Size-optimized pc->line mapping.
61478  */
61479 
61480  DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
61481  duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count); /* -> pushes fixed buffer */
61482  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
61483 
61484  /* XXX: if assertions enabled, walk through all valid PCs
61485  * and check line mapping.
61486  */
61487  }
61488 #endif /* DUK_USE_PC2LINE */
61489 
61490  /* fileName */
61491 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
61492  if (comp_ctx->h_filename) {
61493  /*
61494  * Source filename (or equivalent), for identifying thrown errors.
61495  */
61496 
61497  duk_push_hstring(ctx, comp_ctx->h_filename);
61498  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
61499  }
61500 #endif
61501 
61502  DUK_DD(DUK_DDPRINT("converted function: %!ixT",
61503  (duk_tval *) duk_get_tval(ctx, -1)));
61504 
61505  /*
61506  * Compact the function template.
61507  */
61508 
61509  duk_compact_m1(ctx);
61510 
61511  /*
61512  * Debug dumping
61513  */
61514 
61515 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
61516  {
61517  duk_hcompfunc *h;
61518  duk_instr_t *p, *p_start, *p_end;
61519 
61520  h = (duk_hcompfunc *) duk_get_hobject(ctx, -1);
61521  p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
61522  p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
61523 
61524  p = p_start;
61525  while (p < p_end) {
61526  DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
61527  (long) (p - p_start),
61528  (duk_instr_t) (*p),
61529  (unsigned long) (*p),
61530  (long) DUK_DEC_OP(*p),
61531  (long) DUK_DEC_OP(*p),
61532  (long) DUK_DEC_A(*p),
61533  (long) DUK_DEC_B(*p),
61534  (long) DUK_DEC_C(*p)));
61535  p++;
61536  }
61537  }
61538 #endif
61539 }
61540 
61541 /*
61542  * Code emission helpers
61543  *
61544  * Some emission helpers understand the range of target and source reg/const
61545  * values and automatically emit shuffling code if necessary. This is the
61546  * case when the slot in question (A, B, C) is used in the standard way and
61547  * for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
61548  *
61549  * The standard way is that:
61550  * - slot A is a target register
61551  * - slot B is a source register/constant
61552  * - slot C is a source register/constant
61553  *
61554  * If a slot is used in a non-standard way the caller must indicate this
61555  * somehow. If a slot is used as a target instead of a source (or vice
61556  * versa), this can be indicated with a flag to trigger proper shuffling
61557  * (e.g. DUK__EMIT_FLAG_B_IS_TARGET). If the value in the slot is not
61558  * register/const related at all, the caller must ensure that the raw value
61559  * fits into the corresponding slot so as to not trigger shuffling. The
61560  * caller must set a "no shuffle" flag to ensure compilation fails if
61561  * shuffling were to be triggered because of an internal error.
61562  *
61563  * For slots B and C the raw slot size is 9 bits but one bit is reserved for
61564  * the reg/const indicator. To use the full 9-bit range for a raw value,
61565  * shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
61566  * Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
61567  *
61568  * There is call handling specific understanding in the A-B-C emitter to
61569  * convert call setup and call instructions into indirect ones if necessary.
61570  */
61571 
61572 /* Code emission flags, passed in the 'opcode' field. Opcode + flags
61573  * fit into 16 bits for now, so use duk_small_uint_t.
61574  */
61575 #define DUK__EMIT_FLAG_NO_SHUFFLE_A (1 << 8)
61576 #define DUK__EMIT_FLAG_NO_SHUFFLE_B (1 << 9)
61577 #define DUK__EMIT_FLAG_NO_SHUFFLE_C (1 << 10)
61578 #define DUK__EMIT_FLAG_A_IS_SOURCE (1 << 11) /* slot A is a source (default: target) */
61579 #define DUK__EMIT_FLAG_B_IS_TARGET (1 << 12) /* slot B is a target (default: source) */
61580 #define DUK__EMIT_FLAG_C_IS_TARGET (1 << 13) /* slot C is a target (default: source) */
61581 #define DUK__EMIT_FLAG_BC_REGCONST (1 << 14) /* slots B and C are reg/const */
61582 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT (1 << 15) /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
61583 
61584 /* XXX: macro smaller than call? */
61585 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
61586  duk_compiler_func *func;
61587  func = &comp_ctx->curr_func;
61588  return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
61589 }
61590 
61591 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
61592  DUK_ASSERT(pc >= 0);
61593  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)));
61594  return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
61595 }
61596 
61597 /* emit instruction; could return PC but that's not needed in the majority
61598  * of cases.
61599  */
61600 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
61601 #if defined(DUK_USE_PC2LINE)
61602  duk_int_t line;
61603 #endif
61604  duk_compiler_instr *instr;
61605 
61606  DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
61607  (unsigned long) ins,
61608  (long) comp_ctx->curr_token.start_line,
61609  (long) comp_ctx->prev_token.start_line,
61610  (long) duk__get_current_pc(comp_ctx),
61611  (duk_instr_t) ins));
61612 
61613  instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
61614  DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
61615 
61616 #if defined(DUK_USE_PC2LINE)
61617  /* The line number tracking is a bit inconsistent right now, which
61618  * affects debugger accuracy. Mostly call sites emit opcodes when
61619  * they have parsed a token (say a terminating semicolon) and called
61620  * duk__advance(). In this case the line number of the previous
61621  * token is the most accurate one (except in prologue where
61622  * prev_token.start_line is 0). This is probably not 100% correct
61623  * right now.
61624  */
61625  /* approximation, close enough */
61626  line = comp_ctx->prev_token.start_line;
61627  if (line == 0) {
61628  line = comp_ctx->curr_token.start_line;
61629  }
61630 #endif
61631 
61632  instr->ins = ins;
61633 #if defined(DUK_USE_PC2LINE)
61634  instr->line = line;
61635 #endif
61636 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61637  if (line < comp_ctx->curr_func.min_line) {
61638  comp_ctx->curr_func.min_line = line;
61639  }
61640  if (line > comp_ctx->curr_func.max_line) {
61641  comp_ctx->curr_func.max_line = line;
61642  }
61643 #endif
61644 
61645  /* Limit checks for bytecode byte size and line number. */
61646  if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
61647  goto fail_bc_limit;
61648  }
61649 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
61650 #if defined(DUK_USE_BUFLEN16)
61651  /* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
61652  if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
61653  goto fail_bc_limit;
61654  }
61655 #else
61656  if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
61657  goto fail_bc_limit;
61658  }
61659 #endif
61660 #endif
61661 
61662  return;
61663 
61664  fail_bc_limit:
61665  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
61666 }
61667 
61668 /* Update function min/max line from current token. Needed to improve
61669  * function line range information for debugging, so that e.g. opening
61670  * curly brace is covered by line range even when no opcodes are emitted
61671  * for the line containing the brace.
61672  */
61673 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
61674 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61675  duk_int_t line;
61676 
61677  line = comp_ctx->curr_token.start_line;
61678  if (line == 0) {
61679  return;
61680  }
61681  if (line < comp_ctx->curr_func.min_line) {
61682  comp_ctx->curr_func.min_line = line;
61683  }
61684  if (line > comp_ctx->curr_func.max_line) {
61685  comp_ctx->curr_func.max_line = line;
61686  }
61687 #else
61688  DUK_UNREF(comp_ctx);
61689 #endif
61690 }
61691 
61692 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
61693  duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
61694 }
61695 
61696 /* Important main primitive. */
61697 DUK_LOCAL 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) {
61698  duk_instr_t ins = 0;
61699  duk_int_t a_out = -1;
61700  duk_int_t b_out = -1;
61701  duk_int_t c_out = -1;
61702  duk_int_t tmp;
61703  duk_small_int_t op = op_flags & 0xff;
61704 
61705  DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
61706  (unsigned long) op_flags, (long) a, (long) b, (long) c));
61707 
61708  /* We could rely on max temp/const checks: if they don't exceed BC
61709  * limit, nothing here can either (just asserts would be enough).
61710  * Currently we check for the limits, which provides additional
61711  * protection against creating invalid bytecode due to compiler
61712  * bugs.
61713  */
61714 
61715  DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
61716  DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
61717 
61718  /* Input shuffling happens before the actual operation, while output
61719  * shuffling happens afterwards. Output shuffling decisions are still
61720  * made at the same time to reduce branch clutter; output shuffle decisions
61721  * are recorded into X_out variables.
61722  */
61723 
61724  /* Slot A: currently no support for reg/const. */
61725 
61726 #if defined(DUK_USE_SHUFFLE_TORTURE)
61727  if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
61728 #else
61729  if (a <= DUK_BC_A_MAX) {
61730 #endif
61731  ;
61732  } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
61733  DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
61734  goto error_outofregs;
61735  } else if (a <= DUK_BC_BC_MAX) {
61736  comp_ctx->curr_func.needs_shuffle = 1;
61737  tmp = comp_ctx->curr_func.shuffle1;
61738  if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
61739  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
61740  } else {
61741  /* Output shuffle needed after main operation */
61742  a_out = a;
61743 
61744  /* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
61745  * consecutive.
61746  */
61747  DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
61748  comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1);
61749  if (op == DUK_OP_CSVAR) {
61750  /* For CSVAR the limit is one smaller because output shuffle
61751  * must be able to express 'a + 1' in BC.
61752  */
61753  if (a + 1 > DUK_BC_BC_MAX) {
61754  goto error_outofregs;
61755  }
61756  }
61757  }
61758  a = tmp;
61759  } else {
61760  DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
61761  goto error_outofregs;
61762  }
61763 
61764  /* Slot B: reg/const support, mapped to bit 0 of opcode. */
61765 
61766  if (b & DUK__CONST_MARKER) {
61767  DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
61768  DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
61769  b = b & ~DUK__CONST_MARKER;
61770 #if defined(DUK_USE_SHUFFLE_TORTURE)
61771  if (0) {
61772 #else
61773  if (b <= 0xff) {
61774 #endif
61775  if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
61776  /* Opcode follows B/C reg/const convention. */
61777  DUK_ASSERT((op & 0x01) == 0);
61778  ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0); /* const flag for B */
61779  } else {
61780  DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
61781  }
61782  } else if (b <= DUK_BC_BC_MAX) {
61783  comp_ctx->curr_func.needs_shuffle = 1;
61784  tmp = comp_ctx->curr_func.shuffle2;
61785  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
61786  b = tmp;
61787  } else {
61788  DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
61789  goto error_outofregs;
61790  }
61791  } else {
61792 #if defined(DUK_USE_SHUFFLE_TORTURE)
61793  if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
61794 #else
61795  if (b <= 0xff) {
61796 #endif
61797  ;
61798  } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
61799  if (b > DUK_BC_B_MAX) {
61800  /* Note: 0xff != DUK_BC_B_MAX */
61801  DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
61802  goto error_outofregs;
61803  }
61804  } else if (b <= DUK_BC_BC_MAX) {
61805  comp_ctx->curr_func.needs_shuffle = 1;
61806  tmp = comp_ctx->curr_func.shuffle2;
61807  if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
61808  /* Output shuffle needed after main operation */
61809  b_out = b;
61810  }
61811  if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
61812  if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
61813  /* Special handling for MPUTOBJ/MPUTARR shuffling.
61814  * For each, slot B identifies the first register of a range
61815  * of registers, so normal shuffling won't work. Instead,
61816  * an indirect version of the opcode is used.
61817  */
61818  DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
61819  duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
61820  DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
61821  DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
61822  op_flags++; /* indirect opcode follows direct */
61823  } else {
61824  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
61825  }
61826  }
61827  b = tmp;
61828  } else {
61829  DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
61830  goto error_outofregs;
61831  }
61832  }
61833 
61834  /* Slot C: reg/const support, mapped to bit 1 of opcode. */
61835 
61836  if (c & DUK__CONST_MARKER) {
61837  DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
61838  DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
61839  c = c & ~DUK__CONST_MARKER;
61840 #if defined(DUK_USE_SHUFFLE_TORTURE)
61841  if (0) {
61842 #else
61843  if (c <= 0xff) {
61844 #endif
61845  if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
61846  /* Opcode follows B/C reg/const convention. */
61847  DUK_ASSERT((op & 0x02) == 0);
61848  ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0); /* const flag for C */
61849  } else {
61850  DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
61851  }
61852  } else if (c <= DUK_BC_BC_MAX) {
61853  comp_ctx->curr_func.needs_shuffle = 1;
61854  tmp = comp_ctx->curr_func.shuffle3;
61855  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
61856  c = tmp;
61857  } else {
61858  DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
61859  goto error_outofregs;
61860  }
61861  } else {
61862 #if defined(DUK_USE_SHUFFLE_TORTURE)
61863  if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
61864 #else
61865  if (c <= 0xff) {
61866 #endif
61867  ;
61868  } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
61869  if (c > DUK_BC_C_MAX) {
61870  /* Note: 0xff != DUK_BC_C_MAX */
61871  DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
61872  goto error_outofregs;
61873  }
61874  } else if (c <= DUK_BC_BC_MAX) {
61875  comp_ctx->curr_func.needs_shuffle = 1;
61876  tmp = comp_ctx->curr_func.shuffle3;
61877  if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
61878  /* Output shuffle needed after main operation */
61879  c_out = c;
61880  } else {
61881  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
61882  }
61883  c = tmp;
61884  } else {
61885  DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
61886  goto error_outofregs;
61887  }
61888  }
61889 
61890  /* Main operation */
61891 
61892  DUK_ASSERT_DISABLE(a >= DUK_BC_A_MIN); /* unsigned */
61893  DUK_ASSERT(a <= DUK_BC_A_MAX);
61894  DUK_ASSERT_DISABLE(b >= DUK_BC_B_MIN); /* unsigned */
61895  DUK_ASSERT(b <= DUK_BC_B_MAX);
61896  DUK_ASSERT_DISABLE(c >= DUK_BC_C_MIN); /* unsigned */
61897  DUK_ASSERT(c <= DUK_BC_C_MAX);
61898 
61899  ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
61900  duk__emit(comp_ctx, ins);
61901 
61902  /* NEXTENUM needs a jump slot right after the main instruction.
61903  * When the JUMP is taken, output spilling is not needed so this
61904  * workaround is possible. The jump slot PC is exceptionally
61905  * plumbed through comp_ctx to minimize call sites.
61906  */
61907  if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
61908  comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
61909  duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
61910  }
61911 
61912  /* Output shuffling: only one output register is realistically possible.
61913  *
61914  * (Zero would normally be an OK marker value: if the target register
61915  * was zero, it would never be shuffled. But with DUK_USE_SHUFFLE_TORTURE
61916  * this is no longer true, so use -1 as a marker instead.)
61917  */
61918 
61919  if (a_out >= 0) {
61920  DUK_ASSERT(b_out < 0);
61921  DUK_ASSERT(c_out < 0);
61922  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
61923 
61924  if (op == DUK_OP_CSVAR) {
61925  /* Special handling for CSVAR shuffling. The variable lookup
61926  * results in a <value, this binding> pair in successive
61927  * registers so use two shuffle registers and two output
61928  * loads. (In practice this is dead code because temp/const
61929  * limit is reached first.)
61930  */
61931  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
61932  }
61933  } else if (b_out >= 0) {
61934  DUK_ASSERT(a_out < 0);
61935  DUK_ASSERT(c_out < 0);
61936  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
61937  } else if (c_out >= 0) {
61938  DUK_ASSERT(b_out < 0);
61939  DUK_ASSERT(c_out < 0);
61940  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
61941  }
61942 
61943  return;
61944 
61945  error_outofregs:
61946  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
61947 }
61948 
61949 /* For many of the helpers below it'd be technically correct to add
61950  * "no shuffle" flags for parameters passed in as zero. For example,
61951  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
61952  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags. However, since the
61953  * C value is 0, it'll never get shuffled so adding the flag is just
61954  * unnecessary additional code. This is unfortunately not true for
61955  * "shuffle torture" mode which needs special handling.
61956  */
61957 
61958 DUK_LOCAL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b) {
61959 #if defined(DUK_USE_SHUFFLE_TORTURE)
61960  op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
61961 #endif
61962  duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
61963 }
61964 
61965 DUK_LOCAL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c) {
61966 #if defined(DUK_USE_SHUFFLE_TORTURE)
61967  op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
61968 #endif
61969  duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
61970 }
61971 
61972 #if 0 /* unused */
61973 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
61974 #if defined(DUK_USE_SHUFFLE_TORTURE)
61975  op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
61976 #endif
61977  duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
61978 }
61979 #endif
61980 
61981 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
61982 #if defined(DUK_USE_SHUFFLE_TORTURE)
61983  op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
61984 #endif
61985  duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
61986 }
61987 
61988 DUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc) {
61989  duk_instr_t ins;
61990  duk_int_t tmp;
61991 
61992  /* allow caller to give a const number with the DUK__CONST_MARKER */
61993  bc = bc & (~DUK__CONST_MARKER);
61994 
61995  DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN); /* unsigned */
61996  DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
61997  DUK_ASSERT_DISABLE(bc >= DUK_BC_BC_MIN); /* unsigned */
61998  DUK_ASSERT(bc <= DUK_BC_BC_MAX);
61999  DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
62000 
62001  if (bc <= DUK_BC_BC_MAX) {
62002  ;
62003  } else {
62004  /* No BC shuffling now. */
62005  goto error_outofregs;
62006  }
62007 
62008 #if defined(DUK_USE_SHUFFLE_TORTURE)
62009  if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
62010 #else
62011  if (a <= DUK_BC_A_MAX) {
62012 #endif
62013  ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
62014  duk__emit(comp_ctx, ins);
62015  } else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
62016  goto error_outofregs;
62017  } else if (a <= DUK_BC_BC_MAX) {
62018  comp_ctx->curr_func.needs_shuffle = 1;
62019  tmp = comp_ctx->curr_func.shuffle1;
62020  ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
62021  if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
62022  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
62023  duk__emit(comp_ctx, ins);
62024  } else {
62025  duk__emit(comp_ctx, ins);
62026  duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
62027  }
62028  } else {
62029  goto error_outofregs;
62030  }
62031  return;
62032 
62033  error_outofregs:
62034  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
62035 }
62036 
62037 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
62038 #if defined(DUK_USE_SHUFFLE_TORTURE)
62039  op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
62040 #endif
62041  duk__emit_a_bc(comp_ctx, op, 0, bc);
62042 }
62043 
62044 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
62045  duk_instr_t ins;
62046 
62047  DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN); /* unsigned */
62048  DUK_ASSERT(op <= DUK_BC_OP_MAX);
62049  DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN); /* unsigned */
62050  DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
62051  DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
62052 
62053  if (abc <= DUK_BC_ABC_MAX) {
62054  ;
62055  } else {
62056  goto error_outofregs;
62057  }
62058  ins = DUK_ENC_OP_ABC(op, abc);
62059  DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
62060  (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
62061  (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
62062  (long) abc, (duk_instr_t) ins));
62063  duk__emit(comp_ctx, ins);
62064  return;
62065 
62066  error_outofregs:
62067  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
62068 }
62069 
62070 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) {
62071  /* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
62072  * would only shuffle once (instead of twice). The current code works
62073  * though, and has a smaller compiler footprint.
62074  */
62075 
62076  if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
62077  (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
62078  DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
62079  duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
62080  } else {
62081  duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
62082  duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
62083  DUK_ASSERT(lo >= 0);
62084  DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
62085  (long) reg, (long) val, (long) hi, (long) lo));
62086  duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
62087  duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
62088  }
62089 }
62090 
62091 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
62092  duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
62093 }
62094 
62095 #if defined(DUK_USE_SHUFFLE_TORTURE)
62096 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
62097  * are needed to handle indirect opcodes.
62098  */
62099 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
62100  duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
62101 }
62102 #else
62103 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_reg_t reg, duk_int32_t val) {
62104  /* When torture not enabled, can just use the same helper because
62105  * 'reg' won't get spilled.
62106  */
62107  DUK_ASSERT(reg <= DUK_BC_A_MAX);
62108  duk__emit_load_int32(comp_ctx, reg, val);
62109 }
62110 #endif
62111 
62112 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
62113  duk_int_t curr_pc;
62114  duk_int_t offset;
62115 
62116  curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
62117  offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
62118  DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
62119  DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
62120  duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
62121 }
62122 
62123 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
62124  duk_int_t ret;
62125 
62126  ret = duk__get_current_pc(comp_ctx); /* useful for patching jumps later */
62127  duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
62128  return ret;
62129 }
62130 
62131 /* Insert an empty jump in the middle of code emitted earlier. This is
62132  * currently needed for compiling for-in.
62133  */
62134 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
62135 #if defined(DUK_USE_PC2LINE)
62136  duk_int_t line;
62137 #endif
62138  duk_compiler_instr *instr;
62139  duk_size_t offset;
62140 
62141  offset = jump_pc * sizeof(duk_compiler_instr),
62142  instr = (duk_compiler_instr *) (void *)
62143  DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
62144  &comp_ctx->curr_func.bw_code,
62145  offset,
62146  sizeof(duk_compiler_instr));
62147 
62148 #if defined(DUK_USE_PC2LINE)
62149  line = comp_ctx->curr_token.start_line; /* approximation, close enough */
62150 #endif
62151  instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
62152 #if defined(DUK_USE_PC2LINE)
62153  instr->line = line;
62154 #endif
62155 
62156  DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
62157  if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
62158  goto fail_bc_limit;
62159  }
62160  return;
62161 
62162  fail_bc_limit:
62163  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
62164 }
62165 
62166 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
62167  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
62168  */
62169 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
62170  duk_compiler_instr *instr;
62171  duk_int_t offset;
62172 
62173  /* allow negative PCs, behave as a no-op */
62174  if (jump_pc < 0) {
62175  DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
62176  (long) jump_pc, (long) target_pc));
62177  return;
62178  }
62179  DUK_ASSERT(jump_pc >= 0);
62180 
62181  /* XXX: range assert */
62182  instr = duk__get_instr_ptr(comp_ctx, jump_pc);
62183  DUK_ASSERT(instr != NULL);
62184 
62185  /* XXX: range assert */
62186  offset = target_pc - jump_pc - 1;
62187 
62188  instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
62189  DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
62190  (long) jump_pc, (long) target_pc, (long) offset));
62191 }
62192 
62193 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
62194  duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
62195 }
62196 
62197 DUK_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) {
62198  duk_compiler_instr *instr;
62199 
62200  DUK_ASSERT((reg_catch & DUK__CONST_MARKER) == 0);
62201 
62202  instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
62203  DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
62204  DUK_ASSERT(instr != NULL);
62205  if (const_varname & DUK__CONST_MARKER) {
62206  /* Have a catch variable. */
62207  const_varname = const_varname & (~DUK__CONST_MARKER);
62208  if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
62209  /* Catch attempts to use out-of-range reg/const. Without this
62210  * check Duktape 0.12.0 could generate invalid code which caused
62211  * an assert failure on execution. This error is triggered e.g.
62212  * for functions with a lot of constants and a try-catch statement.
62213  * Shuffling or opcode semantics change is needed to fix the issue.
62214  * See: test-bug-trycatch-many-constants.js.
62215  */
62216  DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
62217  (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
62218  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
62219  }
62220  instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
62221  } else {
62222  /* No catch variable, e.g. a try-finally; replace LDCONST with
62223  * NOP to avoid a bogus LDCONST.
62224  */
62225  instr->ins = DUK_ENC_OP(DUK_OP_NOP);
62226  }
62227 
62228  instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
62229  DUK_ASSERT(instr != NULL);
62230  DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
62231  DUK_ASSERT(flags <= DUK_BC_A_MAX);
62232  instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
62233 }
62234 
62235 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
62236  duk_small_uint_t op;
62237 
62238  op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
62239  duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
62240 }
62241 
62242 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
62243  duk_small_uint_t op;
62244 
62245  op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
62246  duk__emit_bc(comp_ctx, op, regconst); /* helper will remove const flag */
62247 }
62248 
62249 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
62250  duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
62251 }
62252 
62253 /*
62254  * Peephole optimizer for finished bytecode.
62255  *
62256  * Does not remove opcodes; currently only straightens out unconditional
62257  * jump chains which are generated by several control structures.
62258  */
62259 
62260 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
62261  duk_compiler_instr *bc;
62262  duk_small_uint_t iter;
62263  duk_int_t i, n;
62264  duk_int_t count_opt;
62265 
62266  bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
62267 #if defined(DUK_USE_BUFLEN16)
62268  /* No need to assert, buffer size maximum is 0xffff. */
62269 #else
62270  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 */
62271 #endif
62272  n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
62273 
62274  for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
62275  count_opt = 0;
62276 
62277  for (i = 0; i < n; i++) {
62278  duk_instr_t ins;
62279  duk_int_t target_pc1;
62280  duk_int_t target_pc2;
62281 
62282  ins = bc[i].ins;
62283  if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
62284  continue;
62285  }
62286 
62287  target_pc1 = i + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
62288  DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
62289  DUK_ASSERT(target_pc1 >= 0);
62290  DUK_ASSERT(target_pc1 < n);
62291 
62292  /* Note: if target_pc1 == i, we'll optimize a jump to itself.
62293  * This does not need to be checked for explicitly; the case
62294  * is rare and max iter breaks us out.
62295  */
62296 
62297  ins = bc[target_pc1].ins;
62298  if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
62299  continue;
62300  }
62301 
62302  target_pc2 = target_pc1 + 1 + DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS;
62303 
62304  DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
62305  (long) i, (long) target_pc1, (long) target_pc2));
62306 
62307  bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
62308 
62309  count_opt++;
62310  }
62311 
62312  DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
62313 
62314  if (count_opt == 0) {
62315  break;
62316  }
62317  }
62318 }
62319 
62320 /*
62321  * Intermediate value helpers
62322  */
62323 
62324 /* Flags for intermediate value coercions. A flag for using a forced reg
62325  * is not needed, the forced_reg argument suffices and generates better
62326  * code (it is checked as it is used).
62327  */
62328 #define DUK__IVAL_FLAG_ALLOW_CONST (1 << 0) /* allow a constant to be returned */
62329 #define DUK__IVAL_FLAG_REQUIRE_TEMP (1 << 1) /* require a (mutable) temporary as a result (or a const if allowed) */
62330 #define DUK__IVAL_FLAG_REQUIRE_SHORT (1 << 2) /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
62331 
62332 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(ctx,x) */
62333 
62334 #if 0 /* enable manually for dumping */
62335 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
62336 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
62337 
62338 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
62339  DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
62340  (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
62341  duk_get_tval((duk_context *) comp_ctx->thr, x->valstack_idx)));
62342 }
62343 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62344  DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
62345  "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
62346  "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
62347  (long) x->t, (long) x->op,
62348  (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
62349  duk_get_tval((duk_context *) comp_ctx->thr, x->x1.valstack_idx),
62350  (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
62351  duk_get_tval((duk_context *) comp_ctx->thr, x->x2.valstack_idx)));
62352 }
62353 #else
62354 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
62355 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
62356 #endif
62357 
62358 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
62359  x->t = DUK_IVAL_PLAIN;
62360  x->x1.t = DUK_ISPEC_REGCONST;
62361  x->x1.regconst = (duk_regconst_t) regconst;
62362 }
62363 
62364 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62365  x->t = DUK_IVAL_PLAIN;
62366  x->x1.t = DUK_ISPEC_VALUE;
62367  duk_replace((duk_context *) comp_ctx->thr, x->x1.valstack_idx);
62368 }
62369 
62370 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62371  x->t = DUK_IVAL_VAR;
62372  x->x1.t = DUK_ISPEC_VALUE;
62373  duk_replace((duk_context *) comp_ctx->thr, x->x1.valstack_idx);
62374 }
62375 
62376 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
62377  DUK_ASSERT(h != NULL);
62378  duk_push_hstring((duk_context *) comp_ctx->thr, h);
62379  duk__ivalue_var_fromstack(comp_ctx, x);
62380 }
62381 
62382 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
62383  duk_context *ctx = (duk_context *) comp_ctx->thr;
62384 
62385  dst->t = src->t;
62386  dst->regconst = src->regconst;
62387  duk_copy(ctx, src->valstack_idx, dst->valstack_idx);
62388 }
62389 
62390 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
62391  duk_context *ctx = (duk_context *) comp_ctx->thr;
62392 
62393  dst->t = src->t;
62394  dst->op = src->op;
62395  dst->x1.t = src->x1.t;
62396  dst->x1.regconst = src->x1.regconst;
62397  dst->x2.t = src->x2.t;
62398  dst->x2.regconst = src->x2.regconst;
62399  duk_copy(ctx, src->x1.valstack_idx, dst->x1.valstack_idx);
62400  duk_copy(ctx, src->x2.valstack_idx, dst->x2.valstack_idx);
62401 }
62402 
62403 DUK_LOCAL duk_reg_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
62404  duk_reg_t res;
62405 
62406  res = comp_ctx->curr_func.temp_next;
62407  comp_ctx->curr_func.temp_next += num;
62408 
62409  if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) { /* == DUK__MAX_TEMPS is OK */
62410  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
62411  }
62412 
62413  /* maintain highest 'used' temporary, needed to figure out nregs of function */
62414  if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
62415  comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
62416  }
62417 
62418  return res;
62419 }
62420 
62421 DUK_LOCAL duk_reg_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
62422  return duk__alloctemps(comp_ctx, 1);
62423 }
62424 
62425 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_reg_t temp_next) {
62426  comp_ctx->curr_func.temp_next = temp_next;
62427  if (temp_next > comp_ctx->curr_func.temp_max) {
62428  comp_ctx->curr_func.temp_max = temp_next;
62429  }
62430 }
62431 
62432 /* get const for value at valstack top */
62433 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
62434  duk_hthread *thr = comp_ctx->thr;
62435  duk_context *ctx = (duk_context *) thr;
62436  duk_compiler_func *f = &comp_ctx->curr_func;
62437  duk_tval *tv1;
62438  duk_int_t i, n, n_check;
62439 
62440  n = (duk_int_t) duk_get_length(ctx, f->consts_idx);
62441 
62442  tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
62443  DUK_ASSERT(tv1 != NULL);
62444 
62445 #if defined(DUK_USE_FASTINT)
62446  /* Explicit check for fastint downgrade. */
62447  DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
62448 #endif
62449 
62450  /* Sanity workaround for handling functions with a large number of
62451  * constants at least somewhat reasonably. Otherwise checking whether
62452  * we already have the constant would grow very slow (as it is O(N^2)).
62453  */
62454  n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
62455  for (i = 0; i < n_check; i++) {
62456  duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
62457 
62458  /* Strict equality is NOT enough, because we cannot use the same
62459  * constant for e.g. +0 and -0.
62460  */
62461  if (duk_js_samevalue(tv1, tv2)) {
62462  DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
62463  (duk_tval *) tv1, (long) i));
62464  duk_pop(ctx);
62465  return (duk_regconst_t) (i | DUK__CONST_MARKER);
62466  }
62467  }
62468 
62469  if (n > DUK__MAX_CONSTS) {
62470  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
62471  }
62472 
62473  DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
62474  (duk_tval *) tv1, (long) n));
62475  (void) duk_put_prop_index(ctx, f->consts_idx, n); /* invalidates tv1, tv2 */
62476  return (duk_regconst_t) (n | DUK__CONST_MARKER);
62477 }
62478 
62479 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
62480 #if defined(DUK_USE_REFERENCE_COUNTING)
62481  duk_context *ctx = (duk_context *) comp_ctx->thr;
62482  duk_compiler_func *f = &comp_ctx->curr_func;
62483  duk_bool_t ret;
62484 
62485  DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
62486  (void) duk_get_prop_index(ctx, f->consts_idx, (duk_uarridx_t) rc);
62487  ret = !duk_is_number(ctx, -1); /* now only number/string, so conservative check */
62488  duk_pop(ctx);
62489  return ret;
62490 #else
62491  DUK_ASSERT((rc & DUK__CONST_MARKER) == 0); /* caller removes const marker */
62492  return 0;
62493 #endif
62494 }
62495 
62496 /* Get the value represented by an duk_ispec to a register or constant.
62497  * The caller can control the result by indicating whether or not:
62498  *
62499  * (1) a constant is allowed (sometimes the caller needs the result to
62500  * be in a register)
62501  *
62502  * (2) a temporary register is required (usually when caller requires
62503  * the register to be safely mutable; normally either a bound
62504  * register or a temporary register are both OK)
62505  *
62506  * (3) a forced register target needs to be used
62507  *
62508  * Bytecode may be emitted to generate the necessary value. The return
62509  * value is either a register or a constant.
62510  */
62511 
62512 DUK_LOCAL
62513 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
62514  duk_ispec *x,
62515  duk_reg_t forced_reg,
62516  duk_small_uint_t flags) {
62517  duk_hthread *thr = comp_ctx->thr;
62518  duk_context *ctx = (duk_context *) thr;
62519 
62520  DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
62521  "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
62522  (long) x->t,
62523  (long) x->regconst,
62524  (duk_tval *) duk_get_tval(ctx, x->valstack_idx),
62525  (long) forced_reg,
62526  (unsigned long) flags,
62527  (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
62528  (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
62529  (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
62530 
62531  switch (x->t) {
62532  case DUK_ISPEC_VALUE: {
62533  duk_tval *tv;
62534 
62535  tv = DUK_GET_TVAL_POSIDX(ctx, x->valstack_idx);
62536  DUK_ASSERT(tv != NULL);
62537 
62538  switch (DUK_TVAL_GET_TAG(tv)) {
62539  case DUK_TAG_UNDEFINED: {
62540  /* Note: although there is no 'undefined' literal, undefined
62541  * values can occur during compilation as a result of e.g.
62542  * the 'void' operator.
62543  */
62544  duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62545  duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, (duk_regconst_t) dest);
62546  return (duk_regconst_t) dest;
62547  }
62548  case DUK_TAG_NULL: {
62549  duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62550  duk__emit_bc(comp_ctx, DUK_OP_LDNULL, (duk_regconst_t) dest);
62551  return (duk_regconst_t) dest;
62552  }
62553  case DUK_TAG_BOOLEAN: {
62554  duk_reg_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62555  duk__emit_bc(comp_ctx,
62556  (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
62557  (duk_regconst_t) dest);
62558  return (duk_regconst_t) dest;
62559  }
62560  case DUK_TAG_POINTER: {
62561  DUK_UNREACHABLE();
62562  break;
62563  }
62564  case DUK_TAG_STRING: {
62565  duk_hstring *h;
62566  duk_reg_t dest;
62567  duk_regconst_t constidx;
62568 
62569  h = DUK_TVAL_GET_STRING(tv);
62570  DUK_UNREF(h);
62571  DUK_ASSERT(h != NULL);
62572 
62573 #if 0 /* XXX: to be implemented? */
62574  /* Use special opcodes to load short strings */
62575  if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
62576  /* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
62577  } else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
62578  /* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
62579  }
62580 #endif
62581  duk_dup(ctx, x->valstack_idx);
62582  constidx = duk__getconst(comp_ctx);
62583 
62584  if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
62585  return constidx;
62586  }
62587 
62588  dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62589  duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
62590  return (duk_regconst_t) dest;
62591  }
62592  case DUK_TAG_OBJECT: {
62593  DUK_UNREACHABLE();
62594  break;
62595  }
62596  case DUK_TAG_BUFFER: {
62597  DUK_UNREACHABLE();
62598  break;
62599  }
62600  case DUK_TAG_LIGHTFUNC: {
62601  DUK_UNREACHABLE();
62602  break;
62603  }
62604 #if defined(DUK_USE_FASTINT)
62605  case DUK_TAG_FASTINT:
62606 #endif
62607  default: {
62608  /* number */
62609  duk_reg_t dest;
62610  duk_regconst_t constidx;
62611  duk_double_t dval;
62612  duk_int32_t ival;
62613 
62614  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
62615  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
62616  dval = DUK_TVAL_GET_NUMBER(tv);
62617 
62618  if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
62619  /* A number can be loaded either through a constant, using
62620  * LDINT, or using LDINT+LDINTX. LDINT is always a size win,
62621  * LDINT+LDINTX is not if the constant is used multiple times.
62622  * Currently always prefer LDINT+LDINTX over a double constant.
62623  */
62624 
62625  if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
62626  dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62627  duk__emit_load_int32(comp_ctx, dest, ival);
62628  return (duk_regconst_t) dest;
62629  }
62630  }
62631 
62632  duk_dup(ctx, x->valstack_idx);
62633  constidx = duk__getconst(comp_ctx);
62634 
62635  if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
62636  return constidx;
62637  } else {
62638  dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62639  duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, constidx);
62640  return (duk_regconst_t) dest;
62641  }
62642  }
62643  } /* end switch */
62644  }
62645  case DUK_ISPEC_REGCONST: {
62646  if (forced_reg >= 0) {
62647  if (x->regconst & DUK__CONST_MARKER) {
62648  duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
62649  } else if (x->regconst != (duk_regconst_t) forced_reg) {
62650  duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
62651  } else {
62652  ; /* already in correct reg */
62653  }
62654  return (duk_regconst_t) forced_reg;
62655  }
62656 
62657  DUK_ASSERT(forced_reg < 0);
62658  if (x->regconst & DUK__CONST_MARKER) {
62659  if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
62660  duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
62661  duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, (duk_regconst_t) dest, x->regconst);
62662  return (duk_regconst_t) dest;
62663  }
62664  return x->regconst;
62665  }
62666 
62667  DUK_ASSERT(forced_reg < 0 && !(x->regconst & DUK__CONST_MARKER));
62668  if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISTEMP(comp_ctx, x->regconst)) {
62669  duk_reg_t dest = DUK__ALLOCTEMP(comp_ctx);
62670  duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, (duk_regconst_t) dest, x->regconst);
62671  return (duk_regconst_t) dest;
62672  }
62673  return x->regconst;
62674  }
62675  default: {
62676  break;
62677  }
62678  }
62679 
62680  DUK_ERROR_INTERNAL(thr);
62681  return 0;
62682 }
62683 
62684 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_reg_t forced_reg) {
62685  DUK_ASSERT(forced_reg >= 0);
62686  (void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
62687 }
62688 
62689 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
62690  * arithmetic operations, property access, or variable access bytecode.
62691  * The duk_ivalue argument ('x') is converted into a plain value as a
62692  * side effect.
62693  */
62694 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_reg_t forced_reg) {
62695  duk_hthread *thr = comp_ctx->thr;
62696  duk_context *ctx = (duk_context *) thr;
62697 
62698  DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
62699  "forced_reg=%ld",
62700  (long) x->t, (long) x->op,
62701  (long) x->x1.t, (long) x->x1.regconst,
62702  (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
62703  (long) x->x2.t, (long) x->x2.regconst,
62704  (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
62705  (long) forced_reg));
62706 
62707  switch (x->t) {
62708  case DUK_IVAL_PLAIN: {
62709  return;
62710  }
62711  /* XXX: support unary arithmetic ivalues (useful?) */
62712  case DUK_IVAL_ARITH: {
62713  duk_regconst_t arg1;
62714  duk_regconst_t arg2;
62715  duk_reg_t dest;
62716  duk_tval *tv1;
62717  duk_tval *tv2;
62718 
62719  DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
62720 
62721  /* inline arithmetic check for constant values */
62722  /* XXX: use the exactly same arithmetic function here as in executor */
62723  if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
62724  tv1 = DUK_GET_TVAL_POSIDX(ctx, x->x1.valstack_idx);
62725  tv2 = DUK_GET_TVAL_POSIDX(ctx, x->x2.valstack_idx);
62726  DUK_ASSERT(tv1 != NULL);
62727  DUK_ASSERT(tv2 != NULL);
62728 
62729  DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
62730  (duk_tval *) tv1,
62731  (duk_tval *) tv2));
62732 
62733  if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
62734  duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
62735  duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
62736  duk_double_t d3;
62737  duk_bool_t accept_fold = 1;
62738 
62739  DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
62740  (double) d1, (double) d2, (long) x->op));
62741  switch (x->op) {
62742  case DUK_OP_ADD: d3 = d1 + d2; break;
62743  case DUK_OP_SUB: d3 = d1 - d2; break;
62744  case DUK_OP_MUL: d3 = d1 * d2; break;
62745  case DUK_OP_DIV: d3 = d1 / d2; break;
62746  case DUK_OP_EXP: {
62747  d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
62748  break;
62749  }
62750  default: accept_fold = 0; break;
62751  }
62752 
62753  if (accept_fold) {
62754  duk_double_union du;
62755  du.d = d3;
62756  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
62757  d3 = du.d;
62758 
62759  x->t = DUK_IVAL_PLAIN;
62760  DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
62761  DUK_TVAL_SET_NUMBER(tv1, d3); /* old value is number: no refcount */
62762  return;
62763  }
62764  } else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
62765  /* Inline string concatenation. No need to check for
62766  * symbols, as all inputs are valid Ecmascript strings.
62767  */
62768  duk_dup(ctx, x->x1.valstack_idx);
62769  duk_dup(ctx, x->x2.valstack_idx);
62770  duk_concat(ctx, 2);
62771  duk_replace(ctx, x->x1.valstack_idx);
62772  x->t = DUK_IVAL_PLAIN;
62773  DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
62774  return;
62775  }
62776  }
62777 
62778  arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
62779  arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
62780 
62781  /* If forced reg, use it as destination. Otherwise try to
62782  * use either coerced ispec if it is a temporary.
62783  */
62784  if (forced_reg >= 0) {
62785  dest = forced_reg;
62786  } else if (DUK__ISTEMP(comp_ctx, arg1)) {
62787  dest = (duk_reg_t) arg1;
62788  } else if (DUK__ISTEMP(comp_ctx, arg2)) {
62789  dest = (duk_reg_t) arg2;
62790  } else {
62791  dest = DUK__ALLOCTEMP(comp_ctx);
62792  }
62793 
62794  DUK_ASSERT(DUK__ISREG(dest));
62795  duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, (duk_regconst_t) dest, arg1, arg2);
62796 
62797  duk__ivalue_regconst(x, (duk_regconst_t) dest);
62798  return;
62799  }
62800  case DUK_IVAL_PROP: {
62801  /* XXX: very similar to DUK_IVAL_ARITH - merge? */
62802  duk_regconst_t arg1;
62803  duk_regconst_t arg2;
62804  duk_reg_t dest;
62805 
62806  /* Need a short reg/const, does not have to be a mutable temp. */
62807  arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
62808  arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
62809 
62810  /* Pick a destination register. If either base value or key
62811  * happens to be a temp value, reuse it as the destination.
62812  *
62813  * XXX: The temp must be a "mutable" one, i.e. such that no
62814  * other expression is using it anymore. Here this should be
62815  * the case because the value of a property access expression
62816  * is neither the base nor the key, but the lookup result.
62817  */
62818 
62819  if (forced_reg >= 0) {
62820  dest = forced_reg;
62821  } else if (DUK__ISTEMP(comp_ctx, arg1)) {
62822  dest = (duk_reg_t) arg1;
62823  } else if (DUK__ISTEMP(comp_ctx, arg2)) {
62824  dest = (duk_reg_t) arg2;
62825  } else {
62826  dest = DUK__ALLOCTEMP(comp_ctx);
62827  }
62828 
62829  duk__emit_a_b_c(comp_ctx,
62830  DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
62831  (duk_regconst_t) dest,
62832  arg1,
62833  arg2);
62834 
62835  duk__ivalue_regconst(x, (duk_regconst_t) dest);
62836  return;
62837  }
62838  case DUK_IVAL_VAR: {
62839  /* x1 must be a string */
62840  duk_reg_t dest;
62841  duk_reg_t reg_varbind;
62842  duk_regconst_t rc_varname;
62843 
62844  DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
62845 
62846  duk_dup(ctx, x->x1.valstack_idx);
62847  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
62848  duk__ivalue_regconst(x, (duk_regconst_t) reg_varbind);
62849  } else {
62850  dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
62851  duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, (duk_regconst_t) dest, rc_varname);
62852  duk__ivalue_regconst(x, (duk_regconst_t) dest);
62853  }
62854  return;
62855  }
62856  case DUK_IVAL_NONE:
62857  default: {
62858  DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
62859  break;
62860  }
62861  }
62862 
62863  DUK_ERROR_INTERNAL(thr);
62864  return;
62865 }
62866 
62867 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
62868 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62869  duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
62870 }
62871 
62872 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
62873 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62874  duk_reg_t temp;
62875 
62876  /* If duk__ivalue_toplain_raw() allocates a temp, forget it and
62877  * restore next temp state.
62878  */
62879  temp = DUK__GETTEMP(comp_ctx);
62880  duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
62881  DUK__SETTEMP(comp_ctx, temp);
62882 }
62883 
62884 /* Coerce an duk_ivalue to a register or constant; result register may
62885  * be a temp or a bound register.
62886  *
62887  * The duk_ivalue argument ('x') is converted into a regconst as a
62888  * side effect.
62889  */
62890 DUK_LOCAL
62891 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
62892  duk_ivalue *x,
62893  duk_reg_t forced_reg,
62894  duk_small_uint_t flags) {
62895  duk_hthread *thr = comp_ctx->thr;
62896  duk_context *ctx = (duk_context *) thr;
62897  duk_regconst_t reg;
62898  DUK_UNREF(thr);
62899  DUK_UNREF(ctx);
62900 
62901  DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
62902  "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
62903  (long) x->t, (long) x->op,
62904  (long) x->x1.t, (long) x->x1.regconst,
62905  (duk_tval *) duk_get_tval(ctx, x->x1.valstack_idx),
62906  (long) x->x2.t, (long) x->x2.regconst,
62907  (duk_tval *) duk_get_tval(ctx, x->x2.valstack_idx),
62908  (long) forced_reg,
62909  (unsigned long) flags,
62910  (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
62911  (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
62912  (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
62913 
62914  /* first coerce to a plain value */
62915  duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
62916  DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
62917 
62918  /* then to a register */
62919  reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
62920  duk__ivalue_regconst(x, (duk_regconst_t) reg);
62921 
62922  return reg;
62923 }
62924 
62925 DUK_LOCAL duk_reg_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62926  return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
62927 }
62928 
62929 #if 0 /* unused */
62930 DUK_LOCAL duk_reg_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62931  return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
62932 }
62933 #endif
62934 
62935 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
62936  DUK_ASSERT(forced_reg >= 0);
62937  (void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
62938 }
62939 
62940 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62941  return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
62942 }
62943 
62944 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
62945  return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
62946 }
62947 
62948 /* The issues below can be solved with better flags */
62949 
62950 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
62951 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
62952  * register if it might have a side effect. Side-effect free values do not
62953  * need to be coerced.
62954  */
62955 
62956 /*
62957  * Identifier handling
62958  */
62959 
62960 DUK_LOCAL duk_reg_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
62961  duk_hthread *thr = comp_ctx->thr;
62962  duk_context *ctx = (duk_context *) thr;
62963  duk_hstring *h_varname;
62964  duk_reg_t ret;
62965 
62966  DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
62967  (duk_tval *) duk_get_tval(ctx, -1)));
62968 
62969  /*
62970  * Special name handling
62971  */
62972 
62973  h_varname = duk_known_hstring(ctx, -1);
62974 
62975  if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
62976  DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
62977  comp_ctx->curr_func.id_access_arguments = 1;
62978  }
62979 
62980  /*
62981  * Inside one or more 'with' statements fall back to slow path always.
62982  * (See e.g. test-stmt-with.js.)
62983  */
62984 
62985  if (comp_ctx->curr_func.with_depth > 0) {
62986  DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
62987  goto slow_path_own;
62988  }
62989 
62990  /*
62991  * Any catch bindings ("catch (e)") also affect identifier binding.
62992  *
62993  * Currently, the varmap is modified for the duration of the catch
62994  * clause to ensure any identifier accesses with the catch variable
62995  * name will use slow path.
62996  */
62997 
62998  duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
62999  if (duk_is_number(ctx, -1)) {
63000  ret = duk_to_int(ctx, -1);
63001  duk_pop(ctx);
63002  } else {
63003  duk_pop(ctx);
63004  if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
63005  DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
63006  goto slow_path_own;
63007  } else {
63008  /* In this case we're doing a variable lookup that doesn't
63009  * match our own variables, so _Varmap won't be needed at
63010  * run time.
63011  */
63012  DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
63013  goto slow_path_notown;
63014  }
63015  }
63016 
63017  DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
63018  return ret;
63019 
63020  slow_path_notown:
63021  DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
63022 
63023  comp_ctx->curr_func.id_access_slow = 1;
63024  return (duk_reg_t) -1;
63025 
63026  slow_path_own:
63027  DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
63028 
63029  comp_ctx->curr_func.id_access_slow = 1;
63030  comp_ctx->curr_func.id_access_slow_own = 1;
63031  return (duk_reg_t) -1;
63032 }
63033 
63034 /* Lookup an identifier name in the current varmap, indicating whether the
63035  * identifier is register-bound and if not, allocating a constant for the
63036  * identifier name. Returns 1 if register-bound, 0 otherwise. Caller can
63037  * also check (out_reg_varbind >= 0) to check whether or not identifier is
63038  * register bound. The caller must NOT use out_rc_varname at all unless
63039  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
63040  * is unsigned and doesn't have a "unused" / none value.
63041  */
63042 DUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_reg_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {
63043  duk_hthread *thr = comp_ctx->thr;
63044  duk_context *ctx = (duk_context *) thr;
63045  duk_reg_t reg_varbind;
63046  duk_regconst_t rc_varname;
63047 
63048  /* [ ... varname ] */
63049 
63050  duk_dup_top(ctx);
63051  reg_varbind = duk__lookup_active_register_binding(comp_ctx);
63052 
63053  if (reg_varbind >= 0) {
63054  *out_reg_varbind = reg_varbind;
63055  *out_rc_varname = 0; /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
63056  duk_pop(ctx);
63057  return 1;
63058  } else {
63059  rc_varname = duk__getconst(comp_ctx);
63060  *out_reg_varbind = -1;
63061  *out_rc_varname = rc_varname;
63062  return 0;
63063  }
63064 }
63065 
63066 /*
63067  * Label handling
63068  *
63069  * Labels are initially added with flags prohibiting both break and continue.
63070  * When the statement type is finally uncovered (after potentially multiple
63071  * labels), all the labels are updated to allow/prohibit break and continue.
63072  */
63073 
63074 DUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {
63075  duk_hthread *thr = comp_ctx->thr;
63076  duk_context *ctx = (duk_context *) thr;
63077  duk_size_t n;
63078  duk_size_t new_size;
63079  duk_uint8_t *p;
63080  duk_labelinfo *li_start, *li;
63081 
63082  /* Duplicate (shadowing) labels are not allowed, except for the empty
63083  * labels (which are used as default labels for switch and iteration
63084  * statements).
63085  *
63086  * We could also allow shadowing of non-empty pending labels without any
63087  * other issues than breaking the required label shadowing requirements
63088  * of the E5 specification, see Section 12.12.
63089  */
63090 
63091  p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
63092  li_start = (duk_labelinfo *) (void *) p;
63093  li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
63094  n = (duk_size_t) (li - li_start);
63095 
63096  while (li > li_start) {
63097  li--;
63098 
63099  if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
63100  DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
63101  }
63102  }
63103 
63104  duk_push_hstring(ctx, h_label);
63105  DUK_ASSERT(n <= DUK_UARRIDX_MAX); /* label limits */
63106  (void) duk_put_prop_index(ctx, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
63107 
63108  new_size = (n + 1) * sizeof(duk_labelinfo);
63109  duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
63110  /* XXX: spare handling, slow now */
63111 
63112  /* relookup after possible realloc */
63113  p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
63114  li_start = (duk_labelinfo *) (void *) p;
63115  DUK_UNREF(li_start); /* silence scan-build warning */
63116  li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
63117  li--;
63118 
63119  /* Labels can be used for iteration statements but also for other statements,
63120  * in particular a label can be used for a block statement. All cases of a
63121  * named label accept a 'break' so that flag is set here. Iteration statements
63122  * also allow 'continue', so that flag is updated when we figure out the
63123  * statement type.
63124  */
63125 
63126  li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
63127  li->label_id = label_id;
63128  li->h_label = h_label;
63129  li->catch_depth = comp_ctx->curr_func.catch_depth; /* catch depth from current func */
63130  li->pc_label = pc_label;
63131 
63132  DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
63133  (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
63134  (long) li->catch_depth, (long) li->pc_label));
63135 }
63136 
63137 /* Update all labels with matching label_id. */
63138 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
63139  duk_uint8_t *p;
63140  duk_labelinfo *li_start, *li;
63141 
63142  p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
63143  li_start = (duk_labelinfo *) (void *) p;
63144  li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
63145 
63146  /* Match labels starting from latest; once label_id no longer matches, we can
63147  * safely exit without checking the rest of the labels (only the topmost labels
63148  * are ever updated).
63149  */
63150  while (li > li_start) {
63151  li--;
63152 
63153  if (li->label_id != label_id) {
63154  break;
63155  }
63156 
63157  DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
63158  (void *) li, (long) label_id, (long) flags));
63159 
63160  li->flags = flags;
63161  }
63162 }
63163 
63164 /* Lookup active label information. Break/continue distinction is necessary to handle switch
63165  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
63166  *
63167  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
63168  * iteration and switch statements) can. A break will match the closest unlabelled or labelled
63169  * statement. A continue will match the closest unlabelled or labelled iteration statement. It is
63170  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
63171  * be duplicated, the continue cannot match any valid label outside the switch.
63172  *
63173  * A side effect of these rules is that a LABEL statement related to a switch should never actually
63174  * catch a continue abrupt completion at run-time. Hence an INVALID opcode can be placed in the
63175  * continue slot of the switch's LABEL statement.
63176  */
63177 
63178 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
63179 DUK_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) {
63180  duk_hthread *thr = comp_ctx->thr;
63181  duk_context *ctx = (duk_context *) thr;
63182  duk_uint8_t *p;
63183  duk_labelinfo *li_start, *li_end, *li;
63184  duk_bool_t match = 0;
63185 
63186  DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
63187  (duk_heaphdr *) h_label, (long) is_break));
63188 
63189  DUK_UNREF(ctx);
63190 
63191  p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
63192  li_start = (duk_labelinfo *) (void *) p;
63193  li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
63194  li = li_end;
63195 
63196  /* Match labels starting from latest label because there can be duplicate empty
63197  * labels in the label set.
63198  */
63199  while (li > li_start) {
63200  li--;
63201 
63202  if (li->h_label != h_label) {
63203  DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
63204  (long) (li - li_start),
63205  (duk_heaphdr *) li->h_label,
63206  (duk_heaphdr *) h_label));
63207  continue;
63208  }
63209 
63210  DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
63211  (long) (li - li_start), (duk_heaphdr *) h_label));
63212 
63213  /* currently all labels accept a break, so no explicit check for it now */
63214  DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
63215 
63216  if (is_break) {
63217  /* break matches always */
63218  match = 1;
63219  break;
63220  } else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
63221  /* iteration statements allow continue */
63222  match = 1;
63223  break;
63224  } else {
63225  /* continue matched this label -- we can only continue if this is the empty
63226  * label, for which duplication is allowed, and thus there is hope of
63227  * finding a match deeper in the label stack.
63228  */
63229  if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
63230  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
63231  } else {
63232  DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
63233  "allow a continue -> continue lookup deeper in label stack"));
63234  }
63235  }
63236  }
63237  /* XXX: match flag is awkward, rework */
63238  if (!match) {
63239  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
63240  }
63241 
63242  DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
63243  (duk_heaphdr *) h_label, (long) li->label_id,
63244  (long) li->catch_depth, (long) li->pc_label));
63245 
63246  *out_label_id = li->label_id;
63247  *out_label_catch_depth = li->catch_depth;
63248  *out_label_pc = li->pc_label;
63249  *out_is_closest = (li == li_end - 1);
63250 }
63251 
63252 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_int_t len) {
63253  duk_hthread *thr = comp_ctx->thr;
63254  duk_context *ctx = (duk_context *) thr;
63255 
63256  duk_set_length(ctx, comp_ctx->curr_func.labelnames_idx, (duk_size_t) len);
63257  duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * (duk_size_t) len);
63258 }
63259 
63260 /*
63261  * Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
63262  *
63263  * - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
63264  * - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
63265  * - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
63266  */
63267 
63268 /* object literal key tracking flags */
63269 #define DUK__OBJ_LIT_KEY_PLAIN (1 << 0) /* key encountered as a plain property */
63270 #define DUK__OBJ_LIT_KEY_GET (1 << 1) /* key encountered as a getter */
63271 #define DUK__OBJ_LIT_KEY_SET (1 << 2) /* key encountered as a setter */
63272 
63273 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63274  duk_hthread *thr = comp_ctx->thr;
63275  duk_reg_t reg_obj; /* result reg */
63276  duk_reg_t reg_temp; /* temp reg */
63277  duk_reg_t temp_start; /* temp reg value for start of loop */
63278  duk_small_uint_t max_init_values; /* max # of values initialized in one MPUTARR set */
63279  duk_small_uint_t num_values; /* number of values in current MPUTARR set */
63280  duk_uarridx_t curr_idx; /* current (next) array index */
63281  duk_uarridx_t start_idx; /* start array index of current MPUTARR set */
63282  duk_uarridx_t init_idx; /* last array index explicitly initialized, +1 */
63283  duk_bool_t require_comma; /* next loop requires a comma */
63284 
63285  /* DUK_TOK_LBRACKET already eaten, current token is right after that */
63286  DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
63287 
63288  max_init_values = DUK__MAX_ARRAY_INIT_VALUES; /* XXX: depend on available temps? */
63289 
63290  reg_obj = DUK__ALLOCTEMP(comp_ctx);
63291  duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj); /* XXX: patch initial size hint afterwards? */
63292  temp_start = DUK__GETTEMP(comp_ctx);
63293 
63294  /*
63295  * Emit initializers in sets of maximum max_init_values.
63296  * Corner cases such as single value initializers do not have
63297  * special handling now.
63298  *
63299  * Elided elements must not be emitted as 'undefined' values,
63300  * because such values would be enumerable (which is incorrect).
63301  * Also note that trailing elisions must be reflected in the
63302  * length of the final array but cause no elements to be actually
63303  * inserted.
63304  */
63305 
63306  curr_idx = 0;
63307  init_idx = 0; /* tracks maximum initialized index + 1 */
63308  start_idx = 0;
63309  require_comma = 0;
63310 
63311  for (;;) {
63312  num_values = 0;
63313  DUK__SETTEMP(comp_ctx, temp_start);
63314 
63315  if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
63316  break;
63317  }
63318 
63319  for (;;) {
63320  if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
63321  /* the outer loop will recheck and exit */
63322  break;
63323  }
63324 
63325  /* comma check */
63326  if (require_comma) {
63327  if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
63328  /* comma after a value, expected */
63329  duk__advance(comp_ctx);
63330  require_comma = 0;
63331  continue;
63332  } else {
63333  goto syntax_error;
63334  }
63335  } else {
63336  if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
63337  /* elision - flush */
63338  curr_idx++;
63339  duk__advance(comp_ctx);
63340  /* if num_values > 0, MPUTARR emitted by outer loop after break */
63341  break;
63342  }
63343  }
63344  /* else an array initializer element */
63345 
63346  /* initial index */
63347  if (num_values == 0) {
63348  start_idx = curr_idx;
63349  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63350  duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
63351  }
63352 
63353  reg_temp = DUK__ALLOCTEMP(comp_ctx); /* alloc temp just in case, to update max temp */
63354  DUK__SETTEMP(comp_ctx, reg_temp);
63355  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
63356  DUK__SETTEMP(comp_ctx, reg_temp + 1);
63357 
63358  num_values++;
63359  curr_idx++;
63360  require_comma = 1;
63361 
63362  if (num_values >= max_init_values) {
63363  /* MPUTARR emitted by outer loop */
63364  break;
63365  }
63366  }
63367 
63368  if (num_values > 0) {
63369  /* - A is a source register (it's not a write target, but used
63370  * to identify the target object) but can be shuffled.
63371  * - B cannot be shuffled normally because it identifies a range
63372  * of registers, the emitter has special handling for this
63373  * (the "no shuffle" flag must not be set).
63374  * - C is a non-register number and cannot be shuffled, but
63375  * never needs to be.
63376  */
63377  duk__emit_a_b_c(comp_ctx,
63378  DUK_OP_MPUTARR |
63379  DUK__EMIT_FLAG_NO_SHUFFLE_C |
63380  DUK__EMIT_FLAG_A_IS_SOURCE,
63381  (duk_regconst_t) reg_obj,
63382  (duk_regconst_t) temp_start,
63383  (duk_regconst_t) (num_values + 1));
63384  init_idx = start_idx + num_values;
63385 
63386  /* num_values and temp_start reset at top of outer loop */
63387  }
63388  }
63389 
63390  DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
63391  duk__advance(comp_ctx);
63392 
63393  DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
63394  (long) curr_idx, (long) init_idx));
63395 
63396  /* trailing elisions? */
63397  if (curr_idx > init_idx) {
63398  /* yes, must set array length explicitly */
63399  DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
63400  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63401  duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
63402  duk__emit_a_bc(comp_ctx,
63403  DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
63404  (duk_regconst_t) reg_obj,
63405  (duk_regconst_t) reg_temp);
63406  }
63407 
63408  DUK__SETTEMP(comp_ctx, temp_start);
63409 
63410  duk__ivalue_regconst(res, (duk_regconst_t) reg_obj);
63411  return;
63412 
63413  syntax_error:
63414  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
63415 }
63416 
63417 typedef struct {
63418  duk_reg_t reg_obj;
63419  duk_reg_t temp_start;
63420  duk_small_uint_t num_pairs;
63422 
63423 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
63424  if (st->num_pairs > 0) {
63425  /* - A is a source register (it's not a write target, but used
63426  * to identify the target object) but can be shuffled.
63427  * - B cannot be shuffled normally because it identifies a range
63428  * of registers, the emitter has special handling for this
63429  * (the "no shuffle" flag must not be set).
63430  * - C is a non-register number and cannot be shuffled, but
63431  * never needs to be.
63432  */
63433  DUK_ASSERT(st->num_pairs > 0);
63434  duk__emit_a_b_c(comp_ctx,
63435  DUK_OP_MPUTOBJ |
63436  DUK__EMIT_FLAG_NO_SHUFFLE_C |
63437  DUK__EMIT_FLAG_A_IS_SOURCE,
63438  st->reg_obj,
63439  st->temp_start,
63440  st->num_pairs * 2);
63441  st->num_pairs = 0;
63442  }
63443  DUK__SETTEMP(comp_ctx, st->temp_start);
63444 }
63445 
63446 DUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_token *tok, duk_reg_t reg_temp) {
63447  if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
63448  /* same handling for identifiers and strings */
63449  DUK_ASSERT(tok->str1 != NULL);
63450  duk_push_hstring((duk_context *) comp_ctx->thr, tok->str1);
63451  } else if (tok->t == DUK_TOK_NUMBER) {
63452  /* numbers can be loaded as numbers and coerced on the fly */
63453  duk_push_number((duk_context *) comp_ctx->thr, tok->num);
63454  } else {
63455  return 1; /* error */
63456  }
63457 
63458  duk__ivalue_plain_fromstack(comp_ctx, res);
63459  DUK__SETTEMP(comp_ctx, reg_temp + 1);
63460  duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
63461  DUK__SETTEMP(comp_ctx, reg_temp + 1);
63462  return 0;
63463 }
63464 
63465 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63466  duk_hthread *thr = comp_ctx->thr;
63467  duk__objlit_state st;
63468  duk_reg_t reg_temp; /* temp reg */
63469  duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
63470  duk_bool_t first; /* first value: comma must not precede the value */
63471  duk_bool_t is_set, is_get; /* temps */
63472 
63473  DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
63474 
63475  max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS; /* XXX: depend on available temps? */
63476 
63477  st.reg_obj = DUK__ALLOCTEMP(comp_ctx); /* target object */
63478  st.temp_start = DUK__GETTEMP(comp_ctx); /* start of MPUTOBJ argument list */
63479  st.num_pairs = 0; /* number of key/value pairs emitted for current MPUTOBJ set */
63480 
63481  duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj); /* XXX: patch initial size hint afterwards? */
63482 
63483  /*
63484  * Emit initializers in sets of maximum max_init_pairs keys.
63485  * Setter/getter is handled separately and terminates the
63486  * current set of initializer values. Corner cases such as
63487  * single value initializers do not have special handling now.
63488  */
63489 
63490  first = 1;
63491  for (;;) {
63492  /*
63493  * ES5 and ES2015+ provide a lot of different PropertyDefinition
63494  * formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
63495  *
63496  * PropertyName can be IdentifierName (includes reserved words), a string
63497  * literal, or a number literal. Note that IdentifierName allows 'get' and
63498  * 'set' too, so we need to look ahead to the next token to distinguish:
63499  *
63500  * { get : 1 }
63501  *
63502  * and
63503  *
63504  * { get foo() { return 1 } }
63505  * { get get() { return 1 } } // 'get' as getter propertyname
63506  *
63507  * Finally, a trailing comma is allowed.
63508  *
63509  * Key name is coerced to string at compile time (and ends up as a
63510  * a string constant) even for numeric keys (e.g. "{1:'foo'}").
63511  * These could be emitted using e.g. LDINT, but that seems hardly
63512  * worth the effort and would increase code size.
63513  */
63514 
63515  DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
63516  (long) comp_ctx->curr_token.t));
63517 
63518  if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
63519  break;
63520  }
63521 
63522  if (first) {
63523  first = 0;
63524  } else {
63525  if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
63526  goto syntax_error;
63527  }
63528  duk__advance(comp_ctx);
63529  if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
63530  /* trailing comma followed by rcurly */
63531  break;
63532  }
63533  }
63534 
63535  /* Advance to get one step of lookup. */
63536  duk__advance(comp_ctx);
63537 
63538  /* Flush current MPUTOBJ if enough many pairs gathered. */
63539  if (st.num_pairs >= max_init_pairs) {
63540  duk__objlit_flush_keys(comp_ctx, &st);
63541  DUK_ASSERT(st.num_pairs == 0);
63542  }
63543 
63544  /* Reset temp register state and reserve reg_temp and
63545  * reg_temp + 1 for handling the current property.
63546  */
63547  DUK__SETTEMP(comp_ctx, st.temp_start + 2 * st.num_pairs);
63548  reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
63549 
63550  /* NOTE: "get" and "set" are not officially ReservedWords and the lexer
63551  * currently treats them always like ordinary identifiers (DUK_TOK_GET
63552  * and DUK_TOK_SET are unused). They need to be detected based on the
63553  * identifier string content.
63554  */
63555 
63556  is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
63557  comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
63558  is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
63559  comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
63560  if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
63561  /* getter/setter */
63562  duk_int_t fnum;
63563 
63564  duk__objlit_flush_keys(comp_ctx, &st);
63565  DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start); /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
63566  reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
63567 
63568  if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
63569  goto syntax_error;
63570  }
63571 
63572  /* curr_token = get/set name */
63573  fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
63574 
63575  duk__emit_a_bc(comp_ctx,
63576  DUK_OP_CLOSURE,
63577  (duk_regconst_t) (st.temp_start + 1),
63578  (duk_regconst_t) fnum);
63579 
63580  /* Slot C is used in a non-standard fashion (range of regs),
63581  * emitter code has special handling for it (must not set the
63582  * "no shuffle" flag).
63583  */
63584  duk__emit_a_bc(comp_ctx,
63585  (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
63586  st.reg_obj,
63587  st.temp_start); /* temp_start+0 = key, temp_start+1 = closure */
63588 
63589  DUK_ASSERT(st.num_pairs == 0); /* temp state is reset on next loop */
63590 #if defined(DUK_USE_ES6)
63591  } else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
63592  (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
63593  duk_bool_t load_rc;
63594 
63595  load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
63596  DUK_UNREF(load_rc);
63597  DUK_ASSERT(load_rc == 0); /* always succeeds because token is identifier */
63598 
63599  duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
63600  DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
63601  duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
63602 
63603  st.num_pairs++;
63604  } else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
63605  comp_ctx->prev_token.t == DUK_TOK_STRING ||
63606  comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
63607  comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
63608  duk_int_t fnum;
63609 
63610  /* Parsing-wise there's a small hickup here: the token parsing
63611  * state is one step too advanced for the function parse helper
63612  * compared to other cases. The current solution is an extra
63613  * flag to indicate whether function parsing should use the
63614  * current or the previous token to starting parsing from.
63615  */
63616 
63617  if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
63618  goto syntax_error;
63619  }
63620 
63621  fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
63622 
63623  duk__emit_a_bc(comp_ctx,
63624  DUK_OP_CLOSURE,
63625  (duk_regconst_t) (reg_temp + 1),
63626  (duk_regconst_t) fnum);
63627 
63628  st.num_pairs++;
63629 #endif /* DUK_USE_ES6 */
63630  } else {
63631 #if defined(DUK_USE_ES6)
63632  if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
63633  /* ES2015 computed property name. Executor ToPropertyKey()
63634  * coerces the key at runtime.
63635  */
63636  DUK__SETTEMP(comp_ctx, reg_temp);
63637  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
63638  duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
63639 
63640  /* XXX: If next token is '(' we're dealing with
63641  * the method shorthand with a computed name,
63642  * e.g. { [Symbol.for('foo')](a,b) {} }. This
63643  * form is not yet supported and causes a
63644  * SyntaxError on the DUK_TOK_COLON check below.
63645  */
63646  }
63647  else
63648 #endif /* DUK_USE_ES6 */
63649  {
63650  if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
63651  goto syntax_error;
63652  }
63653  }
63654 
63655  duk__advance_expect(comp_ctx, DUK_TOK_COLON);
63656 
63657  DUK__SETTEMP(comp_ctx, reg_temp + 1);
63658  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
63659 
63660  st.num_pairs++;
63661  }
63662  } /* property loop */
63663 
63664  /* Flush remaining properties. */
63665  duk__objlit_flush_keys(comp_ctx, &st);
63666  DUK_ASSERT(st.num_pairs == 0);
63667  DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
63668 
63669  DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
63670  duk__advance(comp_ctx);
63671 
63672  duk__ivalue_regconst(res, (duk_regconst_t) st.reg_obj);
63673  return;
63674 
63675  syntax_error:
63676  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
63677 }
63678 
63679 /* Parse argument list. Arguments are written to temps starting from
63680  * "next temp". Returns number of arguments parsed. Expects left paren
63681  * to be already eaten, and eats the right paren before returning.
63682  */
63683 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63684  duk_int_t nargs = 0;
63685  duk_reg_t reg_temp;
63686 
63687  /* Note: expect that caller has already eaten the left paren */
63688 
63689  DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
63690  (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
63691 
63692  for (;;) {
63693  if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
63694  break;
63695  }
63696  if (nargs > 0) {
63697  duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
63698  }
63699 
63700  /* We want the argument expression value to go to "next temp"
63701  * without additional moves. That should almost always be the
63702  * case, but we double check after expression parsing.
63703  *
63704  * This is not the cleanest possible approach.
63705  */
63706 
63707  reg_temp = DUK__ALLOCTEMP(comp_ctx); /* bump up "allocated" reg count, just in case */
63708  DUK__SETTEMP(comp_ctx, reg_temp);
63709 
63710  /* binding power must be high enough to NOT allow comma expressions directly */
63711  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp); /* always allow 'in', coerce to 'tr' just in case */
63712 
63713  DUK__SETTEMP(comp_ctx, reg_temp + 1);
63714  nargs++;
63715 
63716  DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
63717  }
63718 
63719  /* eat the right paren */
63720  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63721 
63722  DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
63723 
63724  return nargs;
63725 }
63726 
63727 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
63728  /* empty expressions can be detected conveniently with nud/led counts */
63729  return (comp_ctx->curr_func.nud_count == 0) &&
63730  (comp_ctx->curr_func.led_count == 0);
63731 }
63732 
63733 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
63734  duk_hthread *thr = comp_ctx->thr;
63735  duk_context *ctx = (duk_context *) thr;
63736  duk_token *tk;
63737  duk_reg_t temp_at_entry;
63738  duk_small_int_t tok;
63739  duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
63740 
63741  /*
63742  * ctx->prev_token token to process with duk__expr_nud()
63743  * ctx->curr_token updated by caller
63744  *
63745  * Note: the token in the switch below has already been eaten.
63746  */
63747 
63748  temp_at_entry = DUK__GETTEMP(comp_ctx);
63749 
63750  comp_ctx->curr_func.nud_count++;
63751 
63752  tk = &comp_ctx->prev_token;
63753  tok = tk->t;
63754  res->t = DUK_IVAL_NONE;
63755 
63756  DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
63757  (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
63758 
63759  switch (tok) {
63760 
63761  /* PRIMARY EXPRESSIONS */
63762 
63763  case DUK_TOK_THIS: {
63764  duk_reg_t reg_temp;
63765  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63766  duk__emit_bc(comp_ctx,
63767  DUK_OP_LDTHIS,
63768  (duk_regconst_t) reg_temp);
63769  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
63770  return;
63771  }
63772  case DUK_TOK_IDENTIFIER: {
63773  duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
63774  return;
63775  }
63776  case DUK_TOK_NULL: {
63777  duk_push_null(ctx);
63778  goto plain_value;
63779  }
63780  case DUK_TOK_TRUE: {
63781  duk_push_true(ctx);
63782  goto plain_value;
63783  }
63784  case DUK_TOK_FALSE: {
63785  duk_push_false(ctx);
63786  goto plain_value;
63787  }
63788  case DUK_TOK_NUMBER: {
63789  duk_push_number(ctx, tk->num);
63790  goto plain_value;
63791  }
63792  case DUK_TOK_STRING: {
63793  DUK_ASSERT(tk->str1 != NULL);
63794  duk_push_hstring(ctx, tk->str1);
63795  goto plain_value;
63796  }
63797  case DUK_TOK_REGEXP: {
63798 #if defined(DUK_USE_REGEXP_SUPPORT)
63799  duk_reg_t reg_temp;
63800  duk_regconst_t rc_re_bytecode; /* const */
63801  duk_regconst_t rc_re_source; /* const */
63802 
63803  DUK_ASSERT(tk->str1 != NULL);
63804  DUK_ASSERT(tk->str2 != NULL);
63805 
63806  DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
63807  (duk_heaphdr *) tk->str1,
63808  (duk_heaphdr *) tk->str2));
63809 
63810  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63811  duk_push_hstring(ctx, tk->str1);
63812  duk_push_hstring(ctx, tk->str2);
63813 
63814  /* [ ... pattern flags ] */
63815 
63816  duk_regexp_compile(thr);
63817 
63818  /* [ ... escaped_source bytecode ] */
63819 
63820  rc_re_bytecode = duk__getconst(comp_ctx);
63821  rc_re_source = duk__getconst(comp_ctx);
63822 
63823  duk__emit_a_b_c(comp_ctx,
63824  DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
63825  (duk_regconst_t) reg_temp /*a*/,
63826  rc_re_bytecode /*b*/,
63827  rc_re_source /*c*/);
63828 
63829  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
63830  return;
63831 #else /* DUK_USE_REGEXP_SUPPORT */
63832  goto syntax_error;
63833 #endif /* DUK_USE_REGEXP_SUPPORT */
63834  }
63835  case DUK_TOK_LBRACKET: {
63836  DUK_DDD(DUK_DDDPRINT("parsing array literal"));
63837  duk__nud_array_literal(comp_ctx, res);
63838  return;
63839  }
63840  case DUK_TOK_LCURLY: {
63841  DUK_DDD(DUK_DDDPRINT("parsing object literal"));
63842  duk__nud_object_literal(comp_ctx, res);
63843  return;
63844  }
63845  case DUK_TOK_LPAREN: {
63846  duk_bool_t prev_allow_in;
63847 
63848  comp_ctx->curr_func.paren_level++;
63849  prev_allow_in = comp_ctx->curr_func.allow_in;
63850  comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
63851 
63852  duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, terminates at a ')' */
63853 
63854  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
63855  comp_ctx->curr_func.allow_in = prev_allow_in;
63856  comp_ctx->curr_func.paren_level--;
63857  return;
63858  }
63859 
63860  /* MEMBER/NEW/CALL EXPRESSIONS */
63861 
63862  case DUK_TOK_NEW: {
63863  /*
63864  * Parsing an expression starting with 'new' is tricky because
63865  * there are multiple possible productions deriving from
63866  * LeftHandSideExpression which begin with 'new'.
63867  *
63868  * We currently resort to one-token lookahead to distinguish the
63869  * cases. Hopefully this is correct. The binding power must be
63870  * such that parsing ends at an LPAREN (CallExpression) but not at
63871  * a PERIOD or LBRACKET (MemberExpression).
63872  *
63873  * See doc/compiler.rst for discussion on the parsing approach,
63874  * and testcases/test-dev-new.js for a bunch of documented tests.
63875  */
63876 
63877  duk_reg_t reg_target;
63878  duk_int_t nargs;
63879 
63880  DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
63881 
63882  reg_target = DUK__ALLOCTEMP(comp_ctx);
63883  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
63884  DUK__SETTEMP(comp_ctx, reg_target + 1);
63885 
63886  if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
63887  /* 'new' MemberExpression Arguments */
63888  DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
63889  duk__advance(comp_ctx);
63890  nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp", reg_target + 1 */
63891  /* right paren eaten */
63892  } else {
63893  /* 'new' MemberExpression */
63894  DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
63895  nargs = 0;
63896  }
63897 
63898  /* Opcode slot C is used in a non-standard way, so shuffling
63899  * is not allowed.
63900  */
63901  duk__emit_a_bc(comp_ctx,
63902  DUK_OP_NEW | DUK__EMIT_FLAG_NO_SHUFFLE_A,
63903  nargs /*num_args*/,
63904  reg_target /*target*/);
63905 
63906  DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
63907 
63908  duk__ivalue_regconst(res, (duk_regconst_t) reg_target);
63909  return;
63910  }
63911 
63912  /* FUNCTION EXPRESSIONS */
63913 
63914  case DUK_TOK_FUNCTION: {
63915  /* Function expression. Note that any statement beginning with 'function'
63916  * is handled by the statement parser as a function declaration, or a
63917  * non-standard function expression/statement (or a SyntaxError). We only
63918  * handle actual function expressions (occurring inside an expression) here.
63919  *
63920  * O(depth^2) parse count for inner functions is handled by recording a
63921  * lexer offset on the first compilation pass, so that the function can
63922  * be efficiently skipped on the second pass. This is encapsulated into
63923  * duk__parse_func_like_fnum().
63924  */
63925 
63926  duk_reg_t reg_temp;
63927  duk_int_t fnum;
63928 
63929  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63930 
63931  /* curr_token follows 'function' */
63932  fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
63933  DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
63934 
63935  duk__emit_a_bc(comp_ctx,
63936  DUK_OP_CLOSURE,
63937  (duk_regconst_t) reg_temp /*a*/,
63938  (duk_regconst_t) fnum /*bc*/);
63939 
63940  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
63941  return;
63942  }
63943 
63944  /* UNARY EXPRESSIONS */
63945 
63946  case DUK_TOK_DELETE: {
63947  /* Delete semantics are a bit tricky. The description in E5 specification
63948  * is kind of confusing, because it distinguishes between resolvability of
63949  * a reference (which is only known at runtime) seemingly at compile time
63950  * (= SyntaxError throwing).
63951  */
63952  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
63953  if (res->t == DUK_IVAL_VAR) {
63954  /* not allowed in strict mode, regardless of whether resolves;
63955  * in non-strict mode DELVAR handles both non-resolving and
63956  * resolving cases (the specification description is a bit confusing).
63957  */
63958 
63959  duk_reg_t reg_temp;
63960  duk_reg_t reg_varbind;
63961  duk_regconst_t rc_varname;
63962 
63963  if (comp_ctx->curr_func.is_strict) {
63964  DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
63965  }
63966 
63967  DUK__SETTEMP(comp_ctx, temp_at_entry);
63968  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63969 
63970  duk_dup(ctx, res->x1.valstack_idx);
63971  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
63972  /* register bound variables are non-configurable -> always false */
63973  duk__emit_bc(comp_ctx,
63974  DUK_OP_LDFALSE,
63975  (duk_regconst_t) reg_temp);
63976  } else {
63977  duk_dup(ctx, res->x1.valstack_idx);
63978  rc_varname = duk__getconst(comp_ctx);
63979  duk__emit_a_bc(comp_ctx,
63980  DUK_OP_DELVAR,
63981  (duk_regconst_t) reg_temp,
63982  (duk_regconst_t) rc_varname);
63983  }
63984  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
63985  } else if (res->t == DUK_IVAL_PROP) {
63986  duk_reg_t reg_temp;
63987  duk_reg_t reg_obj;
63988  duk_regconst_t rc_key;
63989 
63990  DUK__SETTEMP(comp_ctx, temp_at_entry);
63991  reg_temp = DUK__ALLOCTEMP(comp_ctx);
63992  reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
63993  rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
63994  duk__emit_a_b_c(comp_ctx,
63995  DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
63996  (duk_regconst_t) reg_temp,
63997  (duk_regconst_t) reg_obj,
63998  rc_key);
63999 
64000  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
64001  } else {
64002  /* non-Reference deletion is always 'true', even in strict mode */
64003  duk_push_true(ctx);
64004  goto plain_value;
64005  }
64006  return;
64007  }
64008  case DUK_TOK_VOID: {
64009  duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64010  duk_push_undefined(ctx);
64011  goto plain_value;
64012  }
64013  case DUK_TOK_TYPEOF: {
64014  /* 'typeof' must handle unresolvable references without throwing
64015  * a ReferenceError (E5 Section 11.4.3). Register mapped values
64016  * will never be unresolvable so special handling is only required
64017  * when an identifier is a "slow path" one.
64018  */
64019  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64020 
64021  if (res->t == DUK_IVAL_VAR) {
64022  duk_reg_t reg_varbind;
64023  duk_regconst_t rc_varname;
64024  duk_reg_t reg_temp;
64025 
64026  duk_dup(ctx, res->x1.valstack_idx);
64027  if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
64028  DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
64029  "at compile time, need to use special run-time handling"));
64030  reg_temp = DUK__ALLOCTEMP(comp_ctx);
64031  duk__emit_a_bc(comp_ctx,
64032  DUK_OP_TYPEOFID,
64033  reg_temp,
64034  rc_varname);
64035  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
64036  return;
64037  }
64038  }
64039 
64040  args = DUK_OP_TYPEOF;
64041  goto unary;
64042  }
64043  case DUK_TOK_INCREMENT: {
64044  args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
64045  goto preincdec;
64046  }
64047  case DUK_TOK_DECREMENT: {
64048  args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
64049  goto preincdec;
64050  }
64051  case DUK_TOK_ADD: {
64052  /* unary plus */
64053  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64054  if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
64055  duk_is_number(ctx, res->x1.valstack_idx)) {
64056  /* unary plus of a number is identity */
64057  return;
64058  }
64059  args = DUK_OP_UNP;
64060  goto unary;
64061  }
64062  case DUK_TOK_SUB: {
64063  /* unary minus */
64064  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64065  if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
64066  duk_is_number(ctx, res->x1.valstack_idx)) {
64067  /* this optimization is important to handle negative literals
64068  * (which are not directly provided by the lexical grammar)
64069  */
64070  duk_tval *tv_num;
64071  duk_double_union du;
64072 
64073  tv_num = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
64074  DUK_ASSERT(tv_num != NULL);
64075  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
64076  du.d = DUK_TVAL_GET_NUMBER(tv_num);
64077  du.d = -du.d;
64078  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
64079  DUK_TVAL_SET_NUMBER(tv_num, du.d);
64080  return;
64081  }
64082  args = DUK_OP_UNM;
64083  goto unary;
64084  }
64085  case DUK_TOK_BNOT: {
64086  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64087  args = DUK_OP_BNOT;
64088  goto unary;
64089  }
64090  case DUK_TOK_LNOT: {
64091  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64092  if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
64093  /* Very minimal inlining to handle common idioms '!0' and '!1',
64094  * and also boolean arguments like '!false' and '!true'.
64095  */
64096  duk_tval *tv_val;
64097 
64098  tv_val = DUK_GET_TVAL_POSIDX(ctx, res->x1.valstack_idx);
64099  DUK_ASSERT(tv_val != NULL);
64100  if (DUK_TVAL_IS_NUMBER(tv_val)) {
64101  duk_double_t d;
64102  d = DUK_TVAL_GET_NUMBER(tv_val);
64103  if (d == 0.0) {
64104  /* Matches both +0 and -0 on purpose. */
64105  DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
64106  DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
64107  return;
64108  } else if (d == 1.0) {
64109  DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
64110  DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
64111  return;
64112  }
64113  } else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
64114  duk_small_int_t v;
64115  v = DUK_TVAL_GET_BOOLEAN(tv_val);
64116  DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
64117  DUK_ASSERT(v == 0 || v == 1);
64118  DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
64119  return;
64120  }
64121  }
64122  args = DUK_OP_LNOT;
64123  goto unary;
64124  }
64125 
64126  } /* end switch */
64127 
64128  DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
64129  return;
64130 
64131  unary:
64132  {
64133  /* Unary opcodes use just the 'BC' register source because it
64134  * matches current shuffle limits, and maps cleanly to 16 high
64135  * bits of the opcode.
64136  */
64137 
64138  duk_reg_t reg_src, reg_res;
64139 
64140  reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
64141  if (DUK__ISTEMP(comp_ctx, reg_src)) {
64142  reg_res = reg_src;
64143  } else {
64144  reg_res = DUK__ALLOCTEMP(comp_ctx);
64145  }
64146  duk__emit_a_bc(comp_ctx,
64147  args,
64148  reg_res,
64149  (duk_regconst_t) reg_src);
64150  duk__ivalue_regconst(res, (duk_regconst_t) reg_res);
64151  return;
64152  }
64153 
64154  preincdec:
64155  {
64156  /* preincrement and predecrement */
64157  duk_reg_t reg_res;
64158  duk_small_uint_t args_op1 = args & 0xff; /* DUK_OP_PREINCR/DUK_OP_PREDECR */
64159  duk_small_uint_t args_op2 = args >> 8; /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
64160 
64161  /* Specific assumptions for opcode numbering. */
64162  DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
64163  DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
64164 
64165  reg_res = DUK__ALLOCTEMP(comp_ctx);
64166 
64167  duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/); /* UnaryExpression */
64168  if (res->t == DUK_IVAL_VAR) {
64169  duk_hstring *h_varname;
64170  duk_reg_t reg_varbind;
64171  duk_regconst_t rc_varname;
64172 
64173  h_varname = duk_known_hstring(ctx, res->x1.valstack_idx);
64174 
64175  if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
64176  goto syntax_error;
64177  }
64178 
64179  duk_dup(ctx, res->x1.valstack_idx);
64180  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
64181  duk__emit_a_bc(comp_ctx,
64182  args_op1, /* e.g. DUK_OP_PREINCR */
64183  (duk_regconst_t) reg_res,
64184  (duk_regconst_t) reg_varbind);
64185  } else {
64186  duk__emit_a_bc(comp_ctx,
64187  args_op1 + 4, /* e.g. DUK_OP_PREINCV */
64188  (duk_regconst_t) reg_res,
64189  rc_varname);
64190  }
64191 
64192  DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
64193  (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
64194  } else if (res->t == DUK_IVAL_PROP) {
64195  duk_reg_t reg_obj; /* allocate to reg only (not const) */
64196  duk_regconst_t rc_key;
64197  reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
64198  rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
64199  duk__emit_a_b_c(comp_ctx,
64200  args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_PREINCP */
64201  (duk_regconst_t) reg_res,
64202  (duk_regconst_t) reg_obj,
64203  rc_key);
64204  } else {
64205  /* Technically return value is not needed because INVLHS will
64206  * unconditially throw a ReferenceError. Coercion is necessary
64207  * for proper semantics (consider ToNumber() called for an object).
64208  * Use DUK_OP_UNP with a dummy register to get ToNumber().
64209  */
64210 
64211  duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
64212  duk__emit_bc(comp_ctx,
64213  DUK_OP_UNP,
64214  reg_res); /* for side effects, result ignored */
64215  duk__emit_op_only(comp_ctx,
64216  DUK_OP_INVLHS);
64217  }
64218  DUK__SETTEMP(comp_ctx, reg_res + 1);
64219  duk__ivalue_regconst(res, (duk_regconst_t) reg_res);
64220  return;
64221  }
64222 
64223  plain_value:
64224  {
64225  /* Stack top contains plain value */
64226  duk__ivalue_plain_fromstack(comp_ctx, res);
64227  return;
64228  }
64229 
64230  syntax_error:
64231  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
64232 }
64233 
64234 /* XXX: add flag to indicate whether caller cares about return value; this
64235  * affects e.g. handling of assignment expressions. This change needs API
64236  * changes elsewhere too.
64237  */
64238 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
64239  duk_hthread *thr = comp_ctx->thr;
64240  duk_context *ctx = (duk_context *) thr;
64241  duk_token *tk;
64242  duk_small_int_t tok;
64243  duk_uint32_t args; /* temp variable to pass constants and flags to shared code */
64244 
64245  /*
64246  * ctx->prev_token token to process with duk__expr_led()
64247  * ctx->curr_token updated by caller
64248  */
64249 
64250  comp_ctx->curr_func.led_count++;
64251 
64252  /* The token in the switch has already been eaten here */
64253  tk = &comp_ctx->prev_token;
64254  tok = tk->t;
64255 
64256  DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
64257  (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
64258 
64259  /* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
64260 
64261  switch (tok) {
64262 
64263  /* PRIMARY EXPRESSIONS */
64264 
64265  case DUK_TOK_PERIOD: {
64266  /* Property access expressions are critical for correct LHS ordering,
64267  * see comments in duk__expr()!
64268  *
64269  * A conservative approach would be to use duk__ivalue_totempconst()
64270  * for 'left'. However, allowing a reg-bound variable seems safe here
64271  * and is nice because "foo.bar" is a common expression. If the ivalue
64272  * is used in an expression a GETPROP will occur before any changes to
64273  * the base value can occur. If the ivalue is used as an assignment
64274  * LHS, the assignment code will ensure the base value is safe from
64275  * RHS mutation.
64276  */
64277 
64278  /* XXX: This now coerces an identifier into a GETVAR to a temp, which
64279  * causes an extra LDREG in call setup. It's sufficient to coerce to a
64280  * unary ivalue?
64281  */
64282  duk__ivalue_toplain(comp_ctx, left);
64283 
64284  /* NB: must accept reserved words as property name */
64285  if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
64286  DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
64287  }
64288 
64289  res->t = DUK_IVAL_PROP;
64290  duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
64291  DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
64292  duk_push_hstring(ctx, comp_ctx->curr_token.str1);
64293  duk_replace(ctx, res->x2.valstack_idx);
64294  res->x2.t = DUK_ISPEC_VALUE;
64295 
64296  /* special RegExp literal handling after IdentifierName */
64297  comp_ctx->curr_func.reject_regexp_in_adv = 1;
64298 
64299  duk__advance(comp_ctx);
64300  return;
64301  }
64302  case DUK_TOK_LBRACKET: {
64303  /* Property access expressions are critical for correct LHS ordering,
64304  * see comments in duk__expr()!
64305  */
64306 
64307  /* XXX: optimize temp reg use */
64308  /* XXX: similar coercion issue as in DUK_TOK_PERIOD */
64309  /* XXX: coerce to regs? it might be better for enumeration use, where the
64310  * same PROP ivalue is used multiple times. Or perhaps coerce PROP further
64311  * there?
64312  */
64313  /* XXX: for simple cases like x['y'] an unnecessary LDREG is
64314  * emitted for the base value; could avoid it if we knew that
64315  * the key expression is safe (e.g. just a single literal).
64316  */
64317 
64318  /* The 'left' value must not be a register bound variable
64319  * because it may be mutated during the rest of the expression
64320  * and E5.1 Section 11.2.1 specifies the order of evaluation
64321  * so that the base value is evaluated first.
64322  * See: test-bug-nested-prop-mutate.js.
64323  */
64324  duk__ivalue_totempconst(comp_ctx, left);
64325  duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression, ']' terminates */
64326  duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
64327 
64328  res->t = DUK_IVAL_PROP;
64329  duk__copy_ispec(comp_ctx, &res->x1, &res->x2); /* res.x1 -> res.x2 */
64330  duk__copy_ispec(comp_ctx, &left->x1, &res->x1); /* left.x1 -> res.x1 */
64331  return;
64332  }
64333  case DUK_TOK_LPAREN: {
64334  /* function call */
64335  duk_reg_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
64336  duk_int_t nargs;
64337  duk_small_uint_t call_op = DUK_OP_CALL;
64338 
64339  /* XXX: attempt to get the call result to "next temp" whenever
64340  * possible to avoid unnecessary register shuffles.
64341  */
64342 
64343  /*
64344  * Setup call: target and 'this' binding. Three cases:
64345  *
64346  * 1. Identifier base (e.g. "foo()")
64347  * 2. Property base (e.g. "foo.bar()")
64348  * 3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
64349  */
64350 
64351  if (left->t == DUK_IVAL_VAR) {
64352  duk_hstring *h_varname;
64353  duk_reg_t reg_varbind;
64354  duk_regconst_t rc_varname;
64355 
64356  DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
64357 
64358  h_varname = duk_known_hstring(ctx, left->x1.valstack_idx);
64359  if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
64360  /* Potential direct eval call detected, flag the CALL
64361  * so that a run-time "direct eval" check is made and
64362  * special behavior may be triggered. Note that this
64363  * does not prevent 'eval' from being register bound.
64364  */
64365  DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
64366  "-> using EVALCALL, marking function "
64367  "as may_direct_eval"));
64368  call_op = DUK_OP_EVALCALL;
64369  comp_ctx->curr_func.may_direct_eval = 1;
64370  }
64371 
64372  duk_dup(ctx, left->x1.valstack_idx);
64373  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
64374  duk__emit_a_bc(comp_ctx,
64375  DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
64376  (duk_regconst_t) reg_varbind,
64377  (duk_regconst_t) (reg_cs + 0));
64378  } else {
64379  /* XXX: expand target register or constant field to
64380  * reduce shuffling.
64381  */
64382  DUK_ASSERT(DUK__ISCONST(rc_varname));
64383  duk__emit_a_b(comp_ctx,
64384  DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
64385  (duk_regconst_t) (reg_cs + 0),
64386  rc_varname);
64387  }
64388  } else if (left->t == DUK_IVAL_PROP) {
64389  /* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
64390  * E5 Section 10.4.3. There used to be a separate CSPROP opcode
64391  * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
64392  * CSPROP) and the same can be achieved with ordinary loads.
64393  */
64394  DUK_DDD(DUK_DDDPRINT("function call with property base"));
64395 
64396  duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1); /* base */
64397  duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0); /* base[key] */
64398  } else {
64399  DUK_DDD(DUK_DDDPRINT("function call with register base"));
64400 
64401  duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
64402  duk__emit_a_bc(comp_ctx,
64403  DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
64404  (duk_regconst_t) (reg_cs + 0),
64405  (duk_regconst_t) (reg_cs + 0)); /* in-place setup */
64406  }
64407 
64408  DUK__SETTEMP(comp_ctx, reg_cs + 2);
64409  nargs = duk__parse_arguments(comp_ctx, res); /* parse args starting from "next temp" */
64410 
64411  /* Tailcalls are handled by back-patching the opcode to TAILCALL to the
64412  * already emitted instruction later (in return statement parser).
64413  */
64414 
64415  duk__emit_a_bc(comp_ctx,
64416  call_op | DUK__EMIT_FLAG_NO_SHUFFLE_A,
64417  (duk_regconst_t) nargs /*numargs*/,
64418  (duk_regconst_t) reg_cs /*basereg*/);
64419  DUK__SETTEMP(comp_ctx, reg_cs + 1); /* result in csreg */
64420 
64421  duk__ivalue_regconst(res, (duk_regconst_t) reg_cs);
64422  return;
64423  }
64424 
64425  /* POSTFIX EXPRESSION */
64426 
64427  case DUK_TOK_INCREMENT: {
64428  args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
64429  goto postincdec;
64430  }
64431  case DUK_TOK_DECREMENT: {
64432  args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
64433  goto postincdec;
64434  }
64435 
64436  /* EXPONENTIATION EXPRESSION */
64437 
64438 #if defined(DUK_USE_ES7_EXP_OPERATOR)
64439  case DUK_TOK_EXP: {
64440  args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1; /* UnaryExpression */
64441  goto binary;
64442  }
64443 #endif
64444 
64445  /* MULTIPLICATIVE EXPRESSION */
64446 
64447  case DUK_TOK_MUL: {
64448  args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
64449  goto binary;
64450  }
64451  case DUK_TOK_DIV: {
64452  args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
64453  goto binary;
64454  }
64455  case DUK_TOK_MOD: {
64456  args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE; /* ExponentiationExpression */
64457  goto binary;
64458  }
64459 
64460  /* ADDITIVE EXPRESSION */
64461 
64462  case DUK_TOK_ADD: {
64463  args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
64464  goto binary;
64465  }
64466  case DUK_TOK_SUB: {
64467  args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE; /* MultiplicativeExpression */
64468  goto binary;
64469  }
64470 
64471  /* SHIFT EXPRESSION */
64472 
64473  case DUK_TOK_ALSHIFT: {
64474  /* << */
64475  args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
64476  goto binary;
64477  }
64478  case DUK_TOK_ARSHIFT: {
64479  /* >> */
64480  args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
64481  goto binary;
64482  }
64483  case DUK_TOK_RSHIFT: {
64484  /* >>> */
64485  args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
64486  goto binary;
64487  }
64488 
64489  /* RELATIONAL EXPRESSION */
64490 
64491  case DUK_TOK_LT: {
64492  /* < */
64493  args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
64494  goto binary;
64495  }
64496  case DUK_TOK_GT: {
64497  args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
64498  goto binary;
64499  }
64500  case DUK_TOK_LE: {
64501  args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
64502  goto binary;
64503  }
64504  case DUK_TOK_GE: {
64505  args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
64506  goto binary;
64507  }
64508  case DUK_TOK_INSTANCEOF: {
64509  args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
64510  goto binary;
64511  }
64512  case DUK_TOK_IN: {
64513  args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
64514  goto binary;
64515  }
64516 
64517  /* EQUALITY EXPRESSION */
64518 
64519  case DUK_TOK_EQ: {
64520  args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
64521  goto binary;
64522  }
64523  case DUK_TOK_NEQ: {
64524  args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
64525  goto binary;
64526  }
64527  case DUK_TOK_SEQ: {
64528  args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
64529  goto binary;
64530  }
64531  case DUK_TOK_SNEQ: {
64532  args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
64533  goto binary;
64534  }
64535 
64536  /* BITWISE EXPRESSIONS */
64537 
64538  case DUK_TOK_BAND: {
64539  args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
64540  goto binary;
64541  }
64542  case DUK_TOK_BXOR: {
64543  args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
64544  goto binary;
64545  }
64546  case DUK_TOK_BOR: {
64547  args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
64548  goto binary;
64549  }
64550 
64551  /* LOGICAL EXPRESSIONS */
64552 
64553  case DUK_TOK_LAND: {
64554  /* syntactically left-associative but parsed as right-associative */
64555  args = (1 << 8) + DUK__BP_LAND - 1;
64556  goto binary_logical;
64557  }
64558  case DUK_TOK_LOR: {
64559  /* syntactically left-associative but parsed as right-associative */
64560  args = (0 << 8) + DUK__BP_LOR - 1;
64561  goto binary_logical;
64562  }
64563 
64564  /* CONDITIONAL EXPRESSION */
64565 
64566  case DUK_TOK_QUESTION: {
64567  /* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
64568  * but only if it really is a temp. Nothing fancy here now.
64569  */
64570  duk_reg_t reg_temp;
64571  duk_int_t pc_jump1;
64572  duk_int_t pc_jump2;
64573 
64574  reg_temp = DUK__ALLOCTEMP(comp_ctx);
64575  duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
64576  duk__emit_if_true_skip(comp_ctx, reg_temp);
64577  pc_jump1 = duk__emit_jump_empty(comp_ctx); /* jump to false */
64578  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
64579  duk__advance_expect(comp_ctx, DUK_TOK_COLON);
64580  pc_jump2 = duk__emit_jump_empty(comp_ctx); /* jump to end */
64581  duk__patch_jump_here(comp_ctx, pc_jump1);
64582  duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/); /* AssignmentExpression */
64583  duk__patch_jump_here(comp_ctx, pc_jump2);
64584 
64585  DUK__SETTEMP(comp_ctx, reg_temp + 1);
64586  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
64587  return;
64588  }
64589 
64590  /* ASSIGNMENT EXPRESSION */
64591 
64592  case DUK_TOK_EQUALSIGN: {
64593  /*
64594  * Assignments are right associative, allows e.g.
64595  * a = 5;
64596  * a += b = 9; // same as a += (b = 9)
64597  * -> expression value 14, a = 14, b = 9
64598  *
64599  * Right associativiness is reflected in the BP for recursion,
64600  * "-1" ensures assignment operations are allowed.
64601  *
64602  * XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
64603  */
64604  args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1; /* DUK_OP_NONE marks a 'plain' assignment */
64605  goto assign;
64606  }
64607  case DUK_TOK_ADD_EQ: {
64608  /* right associative */
64609  args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
64610  goto assign;
64611  }
64612  case DUK_TOK_SUB_EQ: {
64613  /* right associative */
64614  args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
64615  goto assign;
64616  }
64617  case DUK_TOK_MUL_EQ: {
64618  /* right associative */
64619  args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
64620  goto assign;
64621  }
64622  case DUK_TOK_DIV_EQ: {
64623  /* right associative */
64624  args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
64625  goto assign;
64626  }
64627  case DUK_TOK_MOD_EQ: {
64628  /* right associative */
64629  args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
64630  goto assign;
64631  }
64632 #if defined(DUK_USE_ES7_EXP_OPERATOR)
64633  case DUK_TOK_EXP_EQ: {
64634  /* right associative */
64635  args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
64636  goto assign;
64637  }
64638 #endif
64639  case DUK_TOK_ALSHIFT_EQ: {
64640  /* right associative */
64641  args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
64642  goto assign;
64643  }
64644  case DUK_TOK_ARSHIFT_EQ: {
64645  /* right associative */
64646  args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
64647  goto assign;
64648  }
64649  case DUK_TOK_RSHIFT_EQ: {
64650  /* right associative */
64651  args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
64652  goto assign;
64653  }
64654  case DUK_TOK_BAND_EQ: {
64655  /* right associative */
64656  args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
64657  goto assign;
64658  }
64659  case DUK_TOK_BOR_EQ: {
64660  /* right associative */
64661  args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
64662  goto assign;
64663  }
64664  case DUK_TOK_BXOR_EQ: {
64665  /* right associative */
64666  args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
64667  goto assign;
64668  }
64669 
64670  /* COMMA */
64671 
64672  case DUK_TOK_COMMA: {
64673  /* right associative */
64674 
64675  duk__ivalue_toplain_ignore(comp_ctx, left); /* need side effects, not value */
64676  duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
64677 
64678  /* return 'res' (of right part) as our result */
64679  return;
64680  }
64681 
64682  default: {
64683  break;
64684  }
64685  }
64686 
64687  DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
64688  DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
64689  return;
64690 
64691 #if 0
64692  /* XXX: shared handling for 'duk__expr_lhs'? */
64693  if (comp_ctx->curr_func.paren_level == 0 && XXX) {
64694  comp_ctx->curr_func.duk__expr_lhs = 0;
64695  }
64696 #endif
64697 
64698  binary:
64699  /*
64700  * Shared handling of binary operations
64701  *
64702  * args = (opcode << 8) + rbp
64703  */
64704  {
64705  duk__ivalue_toplain(comp_ctx, left);
64706  duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
64707 
64708  /* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
64709  DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
64710  DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
64711 
64712  res->t = DUK_IVAL_ARITH;
64713  res->op = (args >> 8) & 0xff;
64714 
64715  res->x2.t = res->x1.t;
64716  res->x2.regconst = res->x1.regconst;
64717  duk_copy(ctx, res->x1.valstack_idx, res->x2.valstack_idx);
64718 
64719  res->x1.t = left->x1.t;
64720  res->x1.regconst = left->x1.regconst;
64721  duk_copy(ctx, left->x1.valstack_idx, res->x1.valstack_idx);
64722 
64723  DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
64724  (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
64725  return;
64726  }
64727 
64728  binary_logical:
64729  /*
64730  * Shared handling for logical AND and logical OR.
64731  *
64732  * args = (truthval << 8) + rbp
64733  *
64734  * Truthval determines when to skip right-hand-side.
64735  * For logical AND truthval=1, for logical OR truthval=0.
64736  *
64737  * See doc/compiler.rst for discussion on compiling logical
64738  * AND and OR expressions. The approach here is very simplistic,
64739  * generating extra jumps and multiple evaluations of truth values,
64740  * but generates code on-the-fly with only local back-patching.
64741  *
64742  * Both logical AND and OR are syntactically left-associated.
64743  * However, logical ANDs are compiled as right associative
64744  * expressions, i.e. "A && B && C" as "A && (B && C)", to allow
64745  * skip jumps to skip over the entire tail. Similarly for logical OR.
64746  */
64747 
64748  {
64749  duk_reg_t reg_temp;
64750  duk_int_t pc_jump;
64751  duk_small_uint_t args_truthval = args >> 8;
64752  duk_small_uint_t args_rbp = args & 0xff;
64753 
64754  /* XXX: unoptimal use of temps, resetting */
64755 
64756  reg_temp = DUK__ALLOCTEMP(comp_ctx);
64757 
64758  duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
64759  DUK_ASSERT(DUK__ISREG(reg_temp));
64760  duk__emit_bc(comp_ctx,
64761  (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
64762  (duk_regconst_t) reg_temp); /* skip jump conditionally */
64763  pc_jump = duk__emit_jump_empty(comp_ctx);
64764  duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
64765  duk__patch_jump_here(comp_ctx, pc_jump);
64766 
64767  duk__ivalue_regconst(res, (duk_regconst_t) reg_temp);
64768  return;
64769  }
64770 
64771  assign:
64772  /*
64773  * Shared assignment expression handling
64774  *
64775  * args = (opcode << 8) + rbp
64776  *
64777  * If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
64778  * Syntactically valid left-hand-side forms which are not accepted as
64779  * left-hand-side values (e.g. as in "f() = 1") must NOT cause a
64780  * SyntaxError, but rather a run-time ReferenceError.
64781  *
64782  * When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
64783  * to a temporary first. The RHS is then evaluated. Finally, the
64784  * <op> is applied to the initial value of RHS (not the value after
64785  * RHS evaluation), and written to X. Doing so concretely generates
64786  * inefficient code so we'd like to avoid the temporary when possible.
64787  * See: https://github.com/svaarala/duktape/pull/992.
64788  *
64789  * The expression value (final LHS value, written to RHS) is
64790  * conceptually copied into a fresh temporary so that it won't
64791  * change even if the LHS/RHS values change in outer expressions.
64792  * For example, it'd be generally incorrect for the expression value
64793  * to be the RHS register binding, unless there's a guarantee that it
64794  * won't change during further expression evaluation. Using the
64795  * temporary concretely produces inefficient bytecode, so we try to
64796  * avoid the extra temporary for some known-to-be-safe cases.
64797  * Currently the only safe case we detect is a "top level assignment",
64798  * for example "x = y + z;", where the assignment expression value is
64799  * ignored.
64800  * See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
64801  */
64802 
64803  {
64804  duk_small_uint_t args_op = args >> 8;
64805  duk_small_uint_t args_rbp = args & 0xff;
64806  duk_bool_t toplevel_assign;
64807 
64808  /* XXX: here we need to know if 'left' is left-hand-side compatible.
64809  * That information is no longer available from current expr parsing
64810  * state; it would need to be carried into the 'left' ivalue or by
64811  * some other means.
64812  */
64813 
64814  /* A top-level assignment is e.g. "x = y;". For these it's safe
64815  * to use the RHS as-is as the expression value, even if the RHS
64816  * is a reg-bound identifier. The RHS ('res') is right associative
64817  * so it has consumed all other assignment level operations; the
64818  * only relevant lower binding power construct is comma operator
64819  * which will ignore the expression value provided here. Usually
64820  * the top level assignment expression value is ignored, but it
64821  * is relevant for e.g. eval code.
64822  */
64823  toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
64824  comp_ctx->curr_func.led_count == 1); /* one operator (= assign) */
64825  DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
64826  (long) comp_ctx->curr_func.nud_count,
64827  (long) comp_ctx->curr_func.led_count,
64828  (long) toplevel_assign));
64829 
64830  if (left->t == DUK_IVAL_VAR) {
64831  duk_hstring *h_varname;
64832  duk_reg_t reg_varbind;
64833  duk_regconst_t rc_varname;
64834 
64835  DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE); /* LHS is already side effect free */
64836 
64837  h_varname = duk_known_hstring(ctx, left->x1.valstack_idx);
64838  if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
64839  /* E5 Section 11.13.1 (and others for other assignments), step 4. */
64840  goto syntax_error_lvalue;
64841  }
64842  duk_dup(ctx, left->x1.valstack_idx);
64843  (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
64844 
64845  if (args_op == DUK_OP_NONE) {
64846  duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
64847  if (toplevel_assign) {
64848  /* Any 'res' will do. */
64849  DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
64850  } else {
64851  /* 'res' must be a plain ivalue, and not register-bound variable. */
64852  DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
64853  if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
64854  (res->x1.regconst & DUK__CONST_MARKER) == 0 &&
64855  !DUK__ISTEMP(comp_ctx, res->x1.regconst))) {
64856  duk__ivalue_totempconst(comp_ctx, res);
64857  }
64858  }
64859  } else {
64860  /* For X <op>= Y we need to evaluate the pre-op
64861  * value of X before evaluating the RHS: the RHS
64862  * can change X, but when we do <op> we must use
64863  * the pre-op value.
64864  */
64865  duk_reg_t reg_temp;
64866 
64867  reg_temp = DUK__ALLOCTEMP(comp_ctx);
64868 
64869  if (reg_varbind >= 0) {
64870  duk_reg_t reg_res;
64871  duk_reg_t reg_src;
64872  duk_int_t pc_temp_load;
64873  duk_int_t pc_before_rhs;
64874  duk_int_t pc_after_rhs;
64875 
64876  if (toplevel_assign) {
64877  /* 'reg_varbind' is the operation result and can also
64878  * become the expression value for top level assignments
64879  * such as: "var x; x += y;".
64880  */
64881  DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
64882  reg_res = reg_varbind;
64883  } else {
64884  /* Not safe to use 'reg_varbind' as assignment expression
64885  * value, so go through a temp.
64886  */
64887  DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
64888  reg_res = reg_temp; /* reg_res should be smallest possible */
64889  reg_temp = DUK__ALLOCTEMP(comp_ctx);
64890  }
64891 
64892  /* Try to optimize X <op>= Y for reg-bound
64893  * variables. Detect side-effect free RHS
64894  * narrowly by seeing whether it emits code.
64895  * If not, rewind the code emitter and overwrite
64896  * the unnecessary temp reg load.
64897  */
64898 
64899  pc_temp_load = duk__get_current_pc(comp_ctx);
64900  duk__emit_a_bc(comp_ctx,
64901  DUK_OP_LDREG,
64902  (duk_regconst_t) reg_temp,
64903  reg_varbind);
64904 
64905  pc_before_rhs = duk__get_current_pc(comp_ctx);
64906  duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
64907  DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
64908  pc_after_rhs = duk__get_current_pc(comp_ctx);
64909 
64910  DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
64911  (long) pc_temp_load, (long) pc_before_rhs,
64912  (long) pc_after_rhs));
64913 
64914  if (pc_after_rhs == pc_before_rhs) {
64915  /* Note: if the reg_temp load generated shuffling
64916  * instructions, we may need to rewind more than
64917  * one instruction, so use explicit PC computation.
64918  */
64919  DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
64920  DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));
64921  reg_src = reg_varbind;
64922  } else {
64923  DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
64924  reg_src = reg_temp;
64925  }
64926 
64927  duk__emit_a_b_c(comp_ctx,
64928  args_op | DUK__EMIT_FLAG_BC_REGCONST,
64929  (duk_regconst_t) reg_res,
64930  (duk_regconst_t) reg_src,
64931  res->x1.regconst);
64932 
64933  res->x1.regconst = (duk_regconst_t) reg_res;
64934 
64935  /* Ensure compact use of temps. */
64936  if (DUK__ISTEMP(comp_ctx, reg_res)) {
64937  DUK__SETTEMP(comp_ctx, reg_res + 1);
64938  }
64939  } else {
64940  /* When LHS is not register bound, always go through a
64941  * temporary. No optimization for top level assignment.
64942  */
64943 
64944  duk__emit_a_bc(comp_ctx,
64945  DUK_OP_GETVAR,
64946  (duk_regconst_t) reg_temp,
64947  rc_varname);
64948 
64949  duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
64950  DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
64951 
64952  duk__emit_a_b_c(comp_ctx,
64953  args_op | DUK__EMIT_FLAG_BC_REGCONST,
64954  (duk_regconst_t) reg_temp,
64955  (duk_regconst_t) reg_temp,
64956  res->x1.regconst);
64957  res->x1.regconst = (duk_regconst_t) reg_temp;
64958  }
64959 
64960  DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
64961  }
64962 
64963  /* At this point 'res' holds the potential expression value.
64964  * It can be basically any ivalue here, including a reg-bound
64965  * identifier (if code above deems it safe) or a unary/binary
64966  * operation. Operations must be resolved to a side effect free
64967  * plain value, and the side effects must happen exactly once.
64968  */
64969 
64970  if (reg_varbind >= 0) {
64971  if (res->t != DUK_IVAL_PLAIN) {
64972  /* Resolve 'res' directly into the LHS binding, and use
64973  * that as the expression value if safe. If not safe,
64974  * resolve to a temp/const and copy to LHS.
64975  */
64976  if (toplevel_assign) {
64977  duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
64978  } else {
64979  duk__ivalue_totempconst(comp_ctx, res);
64980  duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
64981  duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
64982  }
64983  } else {
64984  /* Use 'res' as the expression value (it's side effect
64985  * free and may be a plain value, a register, or a
64986  * constant) and write it to the LHS binding too.
64987  */
64988  duk__copy_ivalue(comp_ctx, res, left); /* use 'left' as a temp */
64989  duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
64990  }
64991  } else {
64992  /* Only a reg fits into 'A' so coerce 'res' into a register
64993  * for PUTVAR.
64994  *
64995  * XXX: here the current A/B/C split is suboptimal: we could
64996  * just use 9 bits for reg_res (and support constants) and 17
64997  * instead of 18 bits for the varname const index.
64998  */
64999 
65000  duk__ivalue_toreg(comp_ctx, res);
65001  duk__emit_a_bc(comp_ctx,
65002  DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
65003  res->x1.regconst,
65004  rc_varname);
65005  }
65006 
65007  /* 'res' contains expression value */
65008  } else if (left->t == DUK_IVAL_PROP) {
65009  /* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
65010  duk_reg_t reg_obj;
65011  duk_regconst_t rc_key;
65012  duk_regconst_t rc_res;
65013  duk_reg_t reg_temp;
65014 
65015  /* Property access expressions ('a[b]') are critical to correct
65016  * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
65017  * We must make sure that the LHS target slot (base object and
65018  * key) don't change during RHS evaluation. The only concrete
65019  * problem is a register reference to a variable-bound register
65020  * (i.e., non-temp). Require temp regs for both key and base.
65021  *
65022  * Don't allow a constant for the object (even for a number
65023  * etc), as it goes into the 'A' field of the opcode.
65024  */
65025 
65026  reg_obj = duk__ispec_toregconst_raw(comp_ctx,
65027  &left->x1,
65028  -1 /*forced_reg*/,
65029  DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
65030 
65031  rc_key = duk__ispec_toregconst_raw(comp_ctx,
65032  &left->x2,
65033  -1 /*forced_reg*/,
65034  DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
65035 
65036  /* Evaluate RHS only when LHS is safe. */
65037 
65038  if (args_op == DUK_OP_NONE) {
65039  duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
65040  DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
65041  rc_res = res->x1.regconst;
65042  } else {
65043  reg_temp = DUK__ALLOCTEMP(comp_ctx);
65044  duk__emit_a_b_c(comp_ctx,
65045  DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
65046  (duk_regconst_t) reg_temp,
65047  (duk_regconst_t) reg_obj,
65048  rc_key);
65049 
65050  duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
65051  DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
65052 
65053  duk__emit_a_b_c(comp_ctx,
65054  args_op | DUK__EMIT_FLAG_BC_REGCONST,
65055  (duk_regconst_t) reg_temp,
65056  (duk_regconst_t) reg_temp,
65057  res->x1.regconst);
65058  rc_res = (duk_regconst_t) reg_temp;
65059  }
65060 
65061  duk__emit_a_b_c(comp_ctx,
65062  DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
65063  (duk_regconst_t) reg_obj,
65064  rc_key,
65065  rc_res);
65066 
65067  duk__ivalue_regconst(res, (duk_regconst_t) rc_res);
65068  } else {
65069  /* No support for lvalues returned from new or function call expressions.
65070  * However, these must NOT cause compile-time SyntaxErrors, but run-time
65071  * ReferenceErrors. Both left and right sides of the assignment must be
65072  * evaluated before throwing a ReferenceError. For instance:
65073  *
65074  * f() = g();
65075  *
65076  * must result in f() being evaluated, then g() being evaluated, and
65077  * finally, a ReferenceError being thrown. See E5 Section 11.13.1.
65078  */
65079 
65080  duk_regconst_t rc_res;
65081 
65082  /* First evaluate LHS fully to ensure all side effects are out. */
65083  duk__ivalue_toplain_ignore(comp_ctx, left);
65084 
65085  /* Then evaluate RHS fully (its value becomes the expression value too).
65086  * Technically we'd need the side effect safety check here too, but because
65087  * we always throw using INVLHS the result doesn't matter.
65088  */
65089  rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
65090 
65091  duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
65092 
65093  duk__ivalue_regconst(res, (duk_regconst_t) rc_res);
65094  }
65095 
65096  return;
65097  }
65098 
65099  postincdec:
65100  {
65101  /*
65102  * Post-increment/decrement will return the original value as its
65103  * result value. However, even that value will be coerced using
65104  * ToNumber() which is quite awkward. Specific bytecode opcodes
65105  * are used to handle these semantics.
65106  *
65107  * Note that post increment/decrement has a "no LineTerminator here"
65108  * restriction. This is handled by duk__expr_lbp(), which forcibly terminates
65109  * the previous expression if a LineTerminator occurs before '++'/'--'.
65110  */
65111 
65112  duk_reg_t reg_res;
65113  duk_small_uint_t args_op1 = (args >> 8) & 0xff; /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
65114  duk_small_uint_t args_op2 = args >> 16; /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
65115 
65116  /* Specific assumptions for opcode numbering. */
65117  DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
65118  DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
65119 
65120  reg_res = DUK__ALLOCTEMP(comp_ctx);
65121 
65122  if (left->t == DUK_IVAL_VAR) {
65123  duk_hstring *h_varname;
65124  duk_reg_t reg_varbind;
65125  duk_regconst_t rc_varname;
65126 
65127  h_varname = duk_known_hstring(ctx, left->x1.valstack_idx);
65128 
65129  if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
65130  goto syntax_error;
65131  }
65132 
65133  duk_dup(ctx, left->x1.valstack_idx);
65134  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
65135  duk__emit_a_bc(comp_ctx,
65136  args_op1, /* e.g. DUK_OP_POSTINCR */
65137  (duk_regconst_t) reg_res,
65138  (duk_regconst_t) reg_varbind);
65139  } else {
65140  duk__emit_a_bc(comp_ctx,
65141  args_op1 + 4, /* e.g. DUK_OP_POSTINCV */
65142  (duk_regconst_t) reg_res,
65143  rc_varname);
65144  }
65145 
65146  DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
65147  (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
65148  } else if (left->t == DUK_IVAL_PROP) {
65149  duk_reg_t reg_obj; /* allocate to reg only (not const) */
65150  duk_regconst_t rc_key;
65151 
65152  reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
65153  rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
65154  duk__emit_a_b_c(comp_ctx,
65155  args_op2 | DUK__EMIT_FLAG_BC_REGCONST, /* e.g. DUK_OP_POSTINCP */
65156  (duk_regconst_t) reg_res,
65157  (duk_regconst_t) reg_obj,
65158  rc_key);
65159  } else {
65160  /* Technically return value is not needed because INVLHS will
65161  * unconditially throw a ReferenceError. Coercion is necessary
65162  * for proper semantics (consider ToNumber() called for an object).
65163  * Use DUK_OP_UNP with a dummy register to get ToNumber().
65164  */
65165  duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
65166  duk__emit_bc(comp_ctx,
65167  DUK_OP_UNP,
65168  reg_res); /* for side effects, result ignored */
65169  duk__emit_op_only(comp_ctx,
65170  DUK_OP_INVLHS);
65171  }
65172 
65173  DUK__SETTEMP(comp_ctx, reg_res + 1);
65174  duk__ivalue_regconst(res, (duk_regconst_t) reg_res);
65175  return;
65176  }
65177 
65178  syntax_error:
65179  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
65180  return;
65181 
65182  syntax_error_lvalue:
65183  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
65184  return;
65185 }
65186 
65187 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
65188  duk_small_int_t tok = comp_ctx->curr_token.t;
65189 
65190  DUK_ASSERT(tok >= DUK_TOK_MINVAL && tok <= DUK_TOK_MAXVAL);
65191  DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
65192 
65193  /* XXX: integrate support for this into led() instead?
65194  * Similar issue as post-increment/post-decrement.
65195  */
65196 
65197  /* prevent duk__expr_led() by using a binding power less than anything valid */
65198  if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
65199  return 0;
65200  }
65201 
65202  if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
65203  (comp_ctx->curr_token.lineterm)) {
65204  /* '++' or '--' in a post-increment/decrement position,
65205  * and a LineTerminator occurs between the operator and
65206  * the preceding expression. Force the previous expr
65207  * to terminate, in effect treating e.g. "a,b\n++" as
65208  * "a,b;++" (= SyntaxError).
65209  */
65210  return 0;
65211  }
65212 
65213  return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]); /* format is bit packed */
65214 }
65215 
65216 /*
65217  * Expression parsing.
65218  *
65219  * Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
65220  * first token of the expression. Upon exit, 'curr_tok' will be the first
65221  * token not part of the expression (e.g. semicolon terminating an expression
65222  * statement).
65223  */
65224 
65225 #define DUK__EXPR_RBP_MASK 0xff
65226 #define DUK__EXPR_FLAG_REJECT_IN (1 << 8) /* reject 'in' token (used for for-in) */
65227 #define DUK__EXPR_FLAG_ALLOW_EMPTY (1 << 9) /* allow empty expression */
65228 #define DUK__EXPR_FLAG_REQUIRE_INIT (1 << 10) /* require initializer for var/const */
65229 
65230 /* main expression parser function */
65231 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65232  duk_hthread *thr = comp_ctx->thr;
65233  duk_context *ctx = (duk_context *) thr;
65234  duk_ivalue tmp_alloc; /* 'res' is used for "left", and 'tmp' for "right" */
65235  duk_ivalue *tmp = &tmp_alloc;
65236  duk_small_uint_t rbp;
65237 
65238  DUK__RECURSION_INCREASE(comp_ctx, thr);
65239 
65240  duk_require_stack(ctx, DUK__PARSE_EXPR_SLOTS);
65241 
65242  /* filter out flags from exprtop rbp_flags here to save space */
65243  rbp = rbp_flags & DUK__EXPR_RBP_MASK;
65244 
65245  DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
65246  (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
65247  (long) comp_ctx->curr_func.paren_level));
65248 
65249  DUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));
65250  tmp->x1.valstack_idx = duk_get_top(ctx);
65251  tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
65252  duk_push_undefined(ctx);
65253  duk_push_undefined(ctx);
65254 
65255  /* XXX: where to release temp regs in intermediate expressions?
65256  * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
65257  * that particular expression temp regs can be forced here.
65258  */
65259 
65260  /* XXX: increase ctx->expr_tokens here for every consumed token
65261  * (this would be a nice statistic)?
65262  */
65263 
65264  if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
65265  /* XXX: possibly incorrect handling of empty expression */
65266  DUK_DDD(DUK_DDDPRINT("empty expression"));
65267  if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
65268  DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
65269  }
65270  duk_push_undefined(ctx);
65271  duk__ivalue_plain_fromstack(comp_ctx, res);
65272  goto cleanup;
65273  }
65274 
65275  duk__advance(comp_ctx);
65276  duk__expr_nud(comp_ctx, res); /* reuse 'res' as 'left' */
65277  while (rbp < duk__expr_lbp(comp_ctx)) {
65278  duk__advance(comp_ctx);
65279  duk__expr_led(comp_ctx, res, tmp);
65280  duk__copy_ivalue(comp_ctx, tmp, res); /* tmp -> res */
65281  }
65282 
65283  cleanup:
65284  /* final result is already in 'res' */
65285 
65286  duk_pop_2(ctx);
65287 
65288  DUK__RECURSION_DECREASE(comp_ctx, thr);
65289 }
65290 
65291 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65292  duk_hthread *thr = comp_ctx->thr;
65293 
65294  /* Note: these variables must reside in 'curr_func' instead of the global
65295  * context: when parsing function expressions, expression parsing is nested.
65296  */
65297  comp_ctx->curr_func.nud_count = 0;
65298  comp_ctx->curr_func.led_count = 0;
65299  comp_ctx->curr_func.paren_level = 0;
65300  comp_ctx->curr_func.expr_lhs = 1;
65301  comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
65302 
65303  duk__expr(comp_ctx, res, rbp_flags);
65304 
65305  if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
65306  DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
65307  }
65308 }
65309 
65310 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
65311  * and result conversions.
65312  *
65313  * Each helper needs at least 2-3 calls to make it worth while to wrap.
65314  */
65315 
65316 #if 0 /* unused */
65317 DUK_LOCAL duk_reg_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65318  duk__expr(comp_ctx, res, rbp_flags);
65319  return duk__ivalue_toreg(comp_ctx, res);
65320 }
65321 #endif
65322 
65323 #if 0 /* unused */
65324 DUK_LOCAL duk_reg_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65325  duk__expr(comp_ctx, res, rbp_flags);
65326  return duk__ivalue_totemp(comp_ctx, res);
65327 }
65328 #endif
65329 
65330 DUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
65331  DUK_ASSERT(forced_reg >= 0);
65332  duk__expr(comp_ctx, res, rbp_flags);
65333  duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
65334 }
65335 
65336 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65337  duk__expr(comp_ctx, res, rbp_flags);
65338  return duk__ivalue_toregconst(comp_ctx, res);
65339 }
65340 
65341 #if 0 /* unused */
65342 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65343  duk__expr(comp_ctx, res, rbp_flags);
65344  return duk__ivalue_totempconst(comp_ctx, res);
65345 }
65346 #endif
65347 
65348 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65349  duk__expr(comp_ctx, res, rbp_flags);
65350  duk__ivalue_toplain(comp_ctx, res);
65351 }
65352 
65353 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65354  duk__expr(comp_ctx, res, rbp_flags);
65355  duk__ivalue_toplain_ignore(comp_ctx, res);
65356 }
65357 
65358 DUK_LOCAL duk_reg_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65359  duk__exprtop(comp_ctx, res, rbp_flags);
65360  return duk__ivalue_toreg(comp_ctx, res);
65361 }
65362 
65363 #if 0 /* unused */
65364 DUK_LOCAL duk_reg_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65365  duk__exprtop(comp_ctx, res, rbp_flags);
65366  return duk__ivalue_totemp(comp_ctx, res);
65367 }
65368 #endif
65369 
65370 DUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_reg_t forced_reg) {
65371  DUK_ASSERT(forced_reg >= 0);
65372  duk__exprtop(comp_ctx, res, rbp_flags);
65373  duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
65374 }
65375 
65376 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
65377  duk__exprtop(comp_ctx, res, rbp_flags);
65378  return duk__ivalue_toregconst(comp_ctx, res);
65379 }
65380 
65381 #if 0 /* unused */
65382 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
65383  duk__exprtop(comp_ctx, res, rbp_flags);
65384  duk__ivalue_toplain_ignore(comp_ctx, res);
65385 }
65386 #endif
65387 
65388 /*
65389  * Parse an individual source element (top level statement) or a statement.
65390  *
65391  * Handles labeled statements automatically (peeling away labels before
65392  * parsing an expression that follows the label(s)).
65393  *
65394  * Upon entry, 'curr_tok' contains the first token of the statement (parsed
65395  * in "allow regexp literal" mode). Upon exit, 'curr_tok' contains the first
65396  * token following the statement (if the statement has a terminator, this is
65397  * the token after the terminator).
65398  */
65399 
65400 #define DUK__HAS_VAL (1 << 0) /* stmt has non-empty value */
65401 #define DUK__HAS_TERM (1 << 1) /* stmt has explicit/implicit semicolon terminator */
65402 #define DUK__ALLOW_AUTO_SEMI_ALWAYS (1 << 2) /* allow automatic semicolon even without lineterm (compatibility) */
65403 #define DUK__STILL_PROLOGUE (1 << 3) /* statement does not terminate directive prologue */
65404 #define DUK__IS_TERMINAL (1 << 4) /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
65405 
65406 /* Parse a single variable declaration (e.g. "i" or "i=10"). A leading 'var'
65407  * has already been eaten. These is no return value in 'res', it is used only
65408  * as a temporary.
65409  *
65410  * When called from 'for-in' statement parser, the initializer expression must
65411  * not allow the 'in' token. The caller supply additional expression parsing
65412  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
65413  *
65414  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
65415  * the identifier is bound:
65416  *
65417  * If register bound: out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
65418  * If not register bound: out_reg_varbind < 0, out_rc_varname >= 0
65419  *
65420  * These allow the caller to use the variable for further assignment, e.g.
65421  * as is done in 'for-in' parsing.
65422  */
65423 
65424 DUK_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) {
65425  duk_hthread *thr = comp_ctx->thr;
65426  duk_context *ctx = (duk_context *) thr;
65427  duk_hstring *h_varname;
65428  duk_reg_t reg_varbind;
65429  duk_regconst_t rc_varname;
65430 
65431  /* assume 'var' has been eaten */
65432 
65433  /* Note: Identifier rejects reserved words */
65434  if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
65435  goto syntax_error;
65436  }
65437  h_varname = comp_ctx->curr_token.str1;
65438 
65439  DUK_ASSERT(h_varname != NULL);
65440 
65441  /* strict mode restrictions (E5 Section 12.2.1) */
65442  if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
65443  goto syntax_error;
65444  }
65445 
65446  /* register declarations in first pass */
65447  if (comp_ctx->curr_func.in_scanning) {
65448  duk_uarridx_t n;
65449  DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
65450  (duk_heaphdr *) h_varname));
65451  n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
65452  duk_push_hstring(ctx, h_varname);
65453  duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
65454  duk_push_int(ctx, DUK_DECL_TYPE_VAR + (0 << 8));
65455  duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
65456  }
65457 
65458  duk_push_hstring(ctx, h_varname); /* push before advancing to keep reachable */
65459 
65460  /* register binding lookup is based on varmap (even in first pass) */
65461  duk_dup_top(ctx);
65462  (void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
65463 
65464  duk__advance(comp_ctx); /* eat identifier */
65465 
65466  if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
65467  duk__advance(comp_ctx);
65468 
65469  DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
65470  (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
65471 
65472  duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/); /* AssignmentExpression */
65473 
65474  if (reg_varbind >= 0) {
65475  duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
65476  } else {
65477  duk_reg_t reg_val;
65478  reg_val = duk__ivalue_toreg(comp_ctx, res);
65479  duk__emit_a_bc(comp_ctx,
65480  DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
65481  (duk_regconst_t) reg_val,
65482  rc_varname);
65483  }
65484  } else {
65485  if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
65486  /* Used for minimal 'const': initializer required. */
65487  goto syntax_error;
65488  }
65489  }
65490 
65491  duk_pop(ctx); /* pop varname */
65492 
65493  *out_rc_varname = rc_varname;
65494  *out_reg_varbind = reg_varbind;
65495 
65496  return;
65497 
65498  syntax_error:
65499  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
65500 }
65501 
65502 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
65503  duk_reg_t reg_varbind;
65504  duk_regconst_t rc_varname;
65505 
65506  duk__advance(comp_ctx); /* eat 'var' */
65507 
65508  for (;;) {
65509  /* rc_varname and reg_varbind are ignored here */
65510  duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
65511 
65512  if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
65513  break;
65514  }
65515  duk__advance(comp_ctx);
65516  }
65517 }
65518 
65519 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
65520  duk_hthread *thr = comp_ctx->thr;
65521  duk_context *ctx = (duk_context *) thr;
65522  duk_int_t pc_v34_lhs; /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
65523  duk_reg_t temp_reset; /* knock back "next temp" to this whenever possible */
65524  duk_reg_t reg_temps; /* preallocated temporaries (2) for variants 3 and 4 */
65525 
65526  DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
65527 
65528  /* Two temporaries are preallocated here for variants 3 and 4 which need
65529  * registers which are never clobbered by expressions in the loop
65530  * (concretely: for the enumerator object and the next enumerated value).
65531  * Variants 1 and 2 "release" these temps.
65532  */
65533 
65534  reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
65535 
65536  temp_reset = DUK__GETTEMP(comp_ctx);
65537 
65538  /*
65539  * For/for-in main variants are:
65540  *
65541  * 1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
65542  * 2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
65543  * 3. for (LeftHandSideExpression in Expression) Statement
65544  * 4. for (var VariableDeclarationNoIn in Expression) Statement
65545  *
65546  * Parsing these without arbitrary lookahead or backtracking is relatively
65547  * tricky but we manage to do so for now.
65548  *
65549  * See doc/compiler.rst for a detailed discussion of control flow
65550  * issues, evaluation order issues, etc.
65551  */
65552 
65553  duk__advance(comp_ctx); /* eat 'for' */
65554  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
65555 
65556  DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
65557 
65558  /* a label site has been emitted by duk__parse_stmt() automatically
65559  * (it will also emit the ENDLABEL).
65560  */
65561 
65562  if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
65563  /*
65564  * Variant 2 or 4
65565  */
65566 
65567  duk_reg_t reg_varbind; /* variable binding register if register-bound (otherwise < 0) */
65568  duk_regconst_t rc_varname; /* variable name reg/const, if variable not register-bound */
65569 
65570  duk__advance(comp_ctx); /* eat 'var' */
65571  duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
65572  DUK__SETTEMP(comp_ctx, temp_reset);
65573 
65574  if (comp_ctx->curr_token.t == DUK_TOK_IN) {
65575  /*
65576  * Variant 4
65577  */
65578 
65579  DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
65580  pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here */
65581  if (reg_varbind >= 0) {
65582  duk__emit_a_bc(comp_ctx,
65583  DUK_OP_LDREG,
65584  (duk_regconst_t) reg_varbind,
65585  (duk_regconst_t) (reg_temps + 0));
65586  } else {
65587  duk__emit_a_bc(comp_ctx,
65588  DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
65589  (duk_regconst_t) (reg_temps + 0),
65590  rc_varname);
65591  }
65592  goto parse_3_or_4;
65593  } else {
65594  /*
65595  * Variant 2
65596  */
65597 
65598  DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
65599  for (;;) {
65600  /* more initializers */
65601  if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
65602  break;
65603  }
65604  DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
65605 
65606  duk__advance(comp_ctx); /* eat comma */
65607  duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
65608  }
65609  goto parse_1_or_2;
65610  }
65611  } else {
65612  /*
65613  * Variant 1 or 3
65614  */
65615 
65616  pc_v34_lhs = duk__get_current_pc(comp_ctx); /* jump is inserted here (variant 3) */
65617 
65618  /* Note that duk__exprtop() here can clobber any reg above current temp_next,
65619  * so any loop variables (e.g. enumerator) must be "preallocated".
65620  */
65621 
65622  /* don't coerce yet to a plain value (variant 3 needs special handling) */
65623  duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression */
65624  if (comp_ctx->curr_token.t == DUK_TOK_IN) {
65625  /*
65626  * Variant 3
65627  */
65628 
65629  /* XXX: need to determine LHS type, and check that it is LHS compatible */
65630  DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
65631  if (duk__expr_is_empty(comp_ctx)) {
65632  goto syntax_error; /* LeftHandSideExpression does not allow empty expression */
65633  }
65634 
65635  if (res->t == DUK_IVAL_VAR) {
65636  duk_reg_t reg_varbind;
65637  duk_regconst_t rc_varname;
65638 
65639  duk_dup(ctx, res->x1.valstack_idx);
65640  if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
65641  duk__emit_a_bc(comp_ctx,
65642  DUK_OP_LDREG,
65643  (duk_regconst_t) reg_varbind,
65644  (duk_regconst_t) (reg_temps + 0));
65645  } else {
65646  duk__emit_a_bc(comp_ctx,
65647  DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
65648  (duk_regconst_t) (reg_temps + 0),
65649  rc_varname);
65650  }
65651  } else if (res->t == DUK_IVAL_PROP) {
65652  /* Don't allow a constant for the object (even for a number etc), as
65653  * it goes into the 'A' field of the opcode.
65654  */
65655  duk_reg_t reg_obj;
65656  duk_regconst_t rc_key;
65657  reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/); /* don't allow const */
65658  rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
65659  duk__emit_a_b_c(comp_ctx,
65660  DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
65661  (duk_regconst_t) reg_obj,
65662  rc_key,
65663  (duk_regconst_t) (reg_temps + 0));
65664  } else {
65665  duk__ivalue_toplain_ignore(comp_ctx, res); /* just in case */
65666  duk__emit_op_only(comp_ctx,
65667  DUK_OP_INVLHS);
65668  }
65669  goto parse_3_or_4;
65670  } else {
65671  /*
65672  * Variant 1
65673  */
65674 
65675  DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
65676  duk__ivalue_toplain_ignore(comp_ctx, res);
65677  goto parse_1_or_2;
65678  }
65679  }
65680 
65681  parse_1_or_2:
65682  /*
65683  * Parse variant 1 or 2. The first part expression (which differs
65684  * in the variants) has already been parsed and its code emitted.
65685  *
65686  * reg_temps + 0: unused
65687  * reg_temps + 1: unused
65688  */
65689  {
65690  duk_regconst_t rc_cond;
65691  duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
65692  duk_int_t pc_jumpto_l3, pc_jumpto_l4;
65693  duk_bool_t expr_c_empty;
65694 
65695  DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
65696 
65697  /* "release" preallocated temps since we won't need them */
65698  temp_reset = reg_temps + 0;
65699  DUK__SETTEMP(comp_ctx, temp_reset);
65700 
65701  duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
65702 
65703  pc_l1 = duk__get_current_pc(comp_ctx);
65704  duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
65705  if (duk__expr_is_empty(comp_ctx)) {
65706  /* no need to coerce */
65707  pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
65708  pc_jumpto_l4 = -1; /* omitted */
65709  } else {
65710  rc_cond = duk__ivalue_toregconst(comp_ctx, res);
65711  duk__emit_if_false_skip(comp_ctx, rc_cond);
65712  pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* to body */
65713  pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx); /* to exit */
65714  }
65715  DUK__SETTEMP(comp_ctx, temp_reset);
65716 
65717  duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
65718 
65719  pc_l2 = duk__get_current_pc(comp_ctx);
65720  duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/); /* Expression_opt */
65721  if (duk__expr_is_empty(comp_ctx)) {
65722  /* no need to coerce */
65723  expr_c_empty = 1;
65724  /* JUMP L1 omitted */
65725  } else {
65726  duk__ivalue_toplain_ignore(comp_ctx, res);
65727  expr_c_empty = 0;
65728  duk__emit_jump(comp_ctx, pc_l1);
65729  }
65730  DUK__SETTEMP(comp_ctx, temp_reset);
65731 
65732  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
65733 
65734  pc_l3 = duk__get_current_pc(comp_ctx);
65735  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
65736  if (expr_c_empty) {
65737  duk__emit_jump(comp_ctx, pc_l1);
65738  } else {
65739  duk__emit_jump(comp_ctx, pc_l2);
65740  }
65741  /* temp reset is not necessary after duk__parse_stmt(), which already does it */
65742 
65743  pc_l4 = duk__get_current_pc(comp_ctx);
65744 
65745  DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
65746  "break: %ld->%ld, continue: %ld->%ld",
65747  (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
65748  (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
65749 
65750  duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
65751  duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
65752  duk__patch_jump(comp_ctx,
65753  pc_label_site + 1,
65754  pc_l4); /* break jump */
65755  duk__patch_jump(comp_ctx,
65756  pc_label_site + 2,
65757  expr_c_empty ? pc_l1 : pc_l2); /* continue jump */
65758  }
65759  goto finished;
65760 
65761  parse_3_or_4:
65762  /*
65763  * Parse variant 3 or 4.
65764  *
65765  * For variant 3 (e.g. "for (A in C) D;") the code for A (except the
65766  * final property/variable write) has already been emitted. The first
65767  * instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
65768  * there to satisfy control flow needs.
65769  *
65770  * For variant 4, if the variable declaration had an initializer
65771  * (e.g. "for (var A = B in C) D;") the code for the assignment
65772  * (B) has already been emitted.
65773  *
65774  * Variables set before entering here:
65775  *
65776  * pc_v34_lhs: insert a "JUMP L2" here (see doc/compiler.rst example).
65777  * reg_temps + 0: iteration target value (written to LHS)
65778  * reg_temps + 1: enumerator object
65779  */
65780  {
65781  duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
65782  duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
65783  duk_reg_t reg_target;
65784 
65785  DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
65786 
65787  DUK__SETTEMP(comp_ctx, temp_reset);
65788 
65789  /* First we need to insert a jump in the middle of previously
65790  * emitted code to get the control flow right. No jumps can
65791  * cross the position where the jump is inserted. See doc/compiler.rst
65792  * for discussion on the intricacies of control flow and side effects
65793  * for variants 3 and 4.
65794  */
65795 
65796  duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
65797  pc_jumpto_l2 = pc_v34_lhs; /* inserted jump */
65798  pc_l1 = pc_v34_lhs + 1; /* +1, right after inserted jump */
65799 
65800  /* The code for writing reg_temps + 0 to the left hand side has already
65801  * been emitted.
65802  */
65803 
65804  pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx); /* -> loop body */
65805 
65806  duk__advance(comp_ctx); /* eat 'in' */
65807 
65808  /* Parse enumeration target and initialize enumerator. For 'null' and 'undefined',
65809  * INITENUM will creates a 'null' enumerator which works like an empty enumerator
65810  * (E5 Section 12.6.4, step 3). Note that INITENUM requires the value to be in a
65811  * register (constant not allowed).
65812  */
65813 
65814  pc_l2 = duk__get_current_pc(comp_ctx);
65815  reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/); /* Expression */
65816  duk__emit_b_c(comp_ctx,
65817  DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
65818  (duk_regconst_t) (reg_temps + 1),
65819  (duk_regconst_t) reg_target);
65820  pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
65821  DUK__SETTEMP(comp_ctx, temp_reset);
65822 
65823  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
65824 
65825  pc_l3 = duk__get_current_pc(comp_ctx);
65826  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
65827  /* temp reset is not necessary after duk__parse_stmt(), which already does it */
65828 
65829  /* NEXTENUM needs a jump slot right after the main opcode.
65830  * We need the code emitter to reserve the slot: if there's
65831  * target shuffling, the target shuffle opcodes must happen
65832  * after the jump slot (for NEXTENUM the shuffle opcodes are
65833  * not needed if the enum is finished).
65834  */
65835  pc_l4 = duk__get_current_pc(comp_ctx);
65836  duk__emit_b_c(comp_ctx,
65837  DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
65838  (duk_regconst_t) (reg_temps + 0),
65839  (duk_regconst_t) (reg_temps + 1));
65840  pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc; /* NEXTENUM jump slot: executed when enum finished */
65841  duk__emit_jump(comp_ctx, pc_l1); /* jump to next loop, using reg_v34_iter as iterated value */
65842 
65843  pc_l5 = duk__get_current_pc(comp_ctx);
65844 
65845  /* XXX: since the enumerator may be a memory expensive object,
65846  * perhaps clear it explicitly here? If so, break jump must
65847  * go through this clearing operation.
65848  */
65849 
65850  DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
65851  "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
65852  "break: %ld->%ld, continue: %ld->%ld",
65853  (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
65854  (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
65855  (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
65856 
65857  duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
65858  duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
65859  duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
65860  duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
65861  duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5); /* break jump */
65862  duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4); /* continue jump */
65863  }
65864  goto finished;
65865 
65866  finished:
65867  DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
65868  return;
65869 
65870  syntax_error:
65871  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
65872 }
65873 
65874 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
65875  duk_hthread *thr = comp_ctx->thr;
65876  duk_reg_t temp_at_loop;
65877  duk_regconst_t rc_switch; /* reg/const for switch value */
65878  duk_regconst_t rc_case; /* reg/const for case value */
65879  duk_reg_t reg_temp; /* general temp register */
65880  duk_int_t pc_prevcase = -1;
65881  duk_int_t pc_prevstmt = -1;
65882  duk_int_t pc_default = -1; /* -1 == not set, -2 == pending (next statement list) */
65883 
65884  /* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
65885 
65886  /*
65887  * Switch is pretty complicated because of several conflicting concerns:
65888  *
65889  * - Want to generate code without an intermediate representation,
65890  * i.e., in one go
65891  *
65892  * - Case selectors are expressions, not values, and may thus e.g. throw
65893  * exceptions (which causes evaluation order concerns)
65894  *
65895  * - Evaluation semantics of case selectors and default clause need to be
65896  * carefully implemented to provide correct behavior even with case value
65897  * side effects
65898  *
65899  * - Fall through case and default clauses; avoiding dead JUMPs if case
65900  * ends with an unconditional jump (a break or a continue)
65901  *
65902  * - The same case value may occur multiple times, but evaluation rules
65903  * only process the first match before switching to a "propagation" mode
65904  * where case values are no longer evaluated
65905  *
65906  * See E5 Section 12.11. Also see doc/compiler.rst for compilation
65907  * discussion.
65908  */
65909 
65910  duk__advance(comp_ctx);
65911  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
65912  rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
65913  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
65914  duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
65915 
65916  DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
65917 
65918  temp_at_loop = DUK__GETTEMP(comp_ctx);
65919 
65920  for (;;) {
65921  duk_int_t num_stmts;
65922  duk_small_int_t tok;
65923 
65924  /* sufficient for keeping temp reg numbers in check */
65925  DUK__SETTEMP(comp_ctx, temp_at_loop);
65926 
65927  if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
65928  break;
65929  }
65930 
65931  /*
65932  * Parse a case or default clause.
65933  */
65934 
65935  if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
65936  /*
65937  * Case clause.
65938  *
65939  * Note: cannot use reg_case as a temp register (for SEQ target)
65940  * because it may be a constant.
65941  */
65942 
65943  duk__patch_jump_here(comp_ctx, pc_prevcase); /* chain jumps for case
65944  * evaluation and checking
65945  */
65946 
65947  duk__advance(comp_ctx);
65948  rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
65949  duk__advance_expect(comp_ctx, DUK_TOK_COLON);
65950 
65951  reg_temp = DUK__ALLOCTEMP(comp_ctx);
65952  duk__emit_a_b_c(comp_ctx,
65953  DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
65954  (duk_regconst_t) reg_temp,
65955  rc_switch,
65956  rc_case);
65957  duk__emit_if_true_skip(comp_ctx, (duk_regconst_t) reg_temp);
65958 
65959  /* jump to next case clause */
65960  pc_prevcase = duk__emit_jump_empty(comp_ctx); /* no match, next case */
65961 
65962  /* statements go here (if any) on next loop */
65963  } else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
65964  /*
65965  * Default clause.
65966  */
65967 
65968  if (pc_default >= 0) {
65969  goto syntax_error;
65970  }
65971  duk__advance(comp_ctx);
65972  duk__advance_expect(comp_ctx, DUK_TOK_COLON);
65973 
65974  /* Fix for https://github.com/svaarala/duktape/issues/155:
65975  * If 'default' is first clause (detected by pc_prevcase < 0)
65976  * we need to ensure we stay in the matching chain.
65977  */
65978  if (pc_prevcase < 0) {
65979  DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
65980  pc_prevcase = duk__emit_jump_empty(comp_ctx);
65981  }
65982 
65983  /* default clause matches next statement list (if any) */
65984  pc_default = -2;
65985  } else {
65986  /* Code is not accepted before the first case/default clause */
65987  goto syntax_error;
65988  }
65989 
65990  /*
65991  * Parse code after the clause. Possible terminators are
65992  * 'case', 'default', and '}'.
65993  *
65994  * Note that there may be no code at all, not even an empty statement,
65995  * between case clauses. This must be handled just like an empty statement
65996  * (omitting seemingly pointless JUMPs), to avoid situations like
65997  * test-bug-case-fallthrough.js.
65998  */
65999 
66000  num_stmts = 0;
66001  if (pc_default == -2) {
66002  pc_default = duk__get_current_pc(comp_ctx);
66003  }
66004 
66005  /* Note: this is correct even for default clause statements:
66006  * they participate in 'fall-through' behavior even if the
66007  * default clause is in the middle.
66008  */
66009  duk__patch_jump_here(comp_ctx, pc_prevstmt); /* chain jumps for 'fall-through'
66010  * after a case matches.
66011  */
66012 
66013  for (;;) {
66014  tok = comp_ctx->curr_token.t;
66015  if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
66016  tok == DUK_TOK_RCURLY) {
66017  break;
66018  }
66019  num_stmts++;
66020  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66021  }
66022 
66023  /* fall-through jump to next code of next case (backpatched) */
66024  pc_prevstmt = duk__emit_jump_empty(comp_ctx);
66025 
66026  /* XXX: would be nice to omit this jump when the jump is not
66027  * reachable, at least in the obvious cases (such as the case
66028  * ending with a 'break'.
66029  *
66030  * Perhaps duk__parse_stmt() could provide some info on whether
66031  * the statement is a "dead end"?
66032  *
66033  * If implemented, just set pc_prevstmt to -1 when not needed.
66034  */
66035  }
66036 
66037  DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
66038  duk__advance(comp_ctx);
66039 
66040  /* default case control flow patchup; note that if pc_prevcase < 0
66041  * (i.e. no case clauses), control enters default case automatically.
66042  */
66043  if (pc_default >= 0) {
66044  /* default case exists: go there if no case matches */
66045  duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
66046  } else {
66047  /* default case does not exist, or no statements present
66048  * after default case: finish case evaluation
66049  */
66050  duk__patch_jump_here(comp_ctx, pc_prevcase);
66051  }
66052 
66053  /* fall-through control flow patchup; note that pc_prevstmt may be
66054  * < 0 (i.e. no case clauses), in which case this is a no-op.
66055  */
66056  duk__patch_jump_here(comp_ctx, pc_prevstmt);
66057 
66058  /* continue jump not patched, an INVALID opcode remains there */
66059  duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
66060 
66061  /* Note: 'fast' breaks will jump to pc_label_site + 1, which will
66062  * then jump here. The double jump will be eliminated by a
66063  * peephole pass, resulting in an optimal jump here. The label
66064  * site jumps will remain in bytecode and will waste code size.
66065  */
66066 
66067  return;
66068 
66069  syntax_error:
66070  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
66071 }
66072 
66073 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66074  duk_reg_t temp_reset;
66075  duk_regconst_t rc_cond;
66076  duk_int_t pc_jump_false;
66077 
66078  DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
66079 
66080  temp_reset = DUK__GETTEMP(comp_ctx);
66081 
66082  duk__advance(comp_ctx); /* eat 'if' */
66083  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
66084 
66085  rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66086  duk__emit_if_true_skip(comp_ctx, rc_cond);
66087  pc_jump_false = duk__emit_jump_empty(comp_ctx); /* jump to end or else part */
66088  DUK__SETTEMP(comp_ctx, temp_reset);
66089 
66090  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
66091 
66092  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66093 
66094  /* The 'else' ambiguity is resolved by 'else' binding to the innermost
66095  * construct, so greedy matching is correct here.
66096  */
66097 
66098  if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
66099  duk_int_t pc_jump_end;
66100 
66101  DUK_DDD(DUK_DDDPRINT("if has else part"));
66102 
66103  duk__advance(comp_ctx);
66104 
66105  pc_jump_end = duk__emit_jump_empty(comp_ctx); /* jump from true part to end */
66106  duk__patch_jump_here(comp_ctx, pc_jump_false);
66107 
66108  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66109 
66110  duk__patch_jump_here(comp_ctx, pc_jump_end);
66111  } else {
66112  DUK_DDD(DUK_DDDPRINT("if does not have else part"));
66113 
66114  duk__patch_jump_here(comp_ctx, pc_jump_false);
66115  }
66116 
66117  DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
66118 }
66119 
66120 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
66121  duk_regconst_t rc_cond;
66122  duk_int_t pc_start;
66123 
66124  DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
66125 
66126  duk__advance(comp_ctx); /* eat 'do' */
66127 
66128  pc_start = duk__get_current_pc(comp_ctx);
66129  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66130  duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
66131 
66132  duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
66133  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
66134 
66135  rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66136  duk__emit_if_false_skip(comp_ctx, rc_cond);
66137  duk__emit_jump(comp_ctx, pc_start);
66138  /* no need to reset temps, as we're finished emitting code */
66139 
66140  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
66141 
66142  duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
66143 
66144  DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
66145 }
66146 
66147 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
66148  duk_reg_t temp_reset;
66149  duk_regconst_t rc_cond;
66150  duk_int_t pc_start;
66151  duk_int_t pc_jump_false;
66152 
66153  DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
66154 
66155  temp_reset = DUK__GETTEMP(comp_ctx);
66156 
66157  duk__advance(comp_ctx); /* eat 'while' */
66158 
66159  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
66160 
66161  pc_start = duk__get_current_pc(comp_ctx);
66162  duk__patch_jump_here(comp_ctx, pc_label_site + 2); /* continue jump */
66163 
66164  rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66165  duk__emit_if_true_skip(comp_ctx, rc_cond);
66166  pc_jump_false = duk__emit_jump_empty(comp_ctx);
66167  DUK__SETTEMP(comp_ctx, temp_reset);
66168 
66169  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
66170 
66171  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66172  duk__emit_jump(comp_ctx, pc_start);
66173 
66174  duk__patch_jump_here(comp_ctx, pc_jump_false);
66175  duk__patch_jump_here(comp_ctx, pc_label_site + 1); /* break jump */
66176 
66177  DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
66178 }
66179 
66180 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66181  duk_hthread *thr = comp_ctx->thr;
66182  duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
66183  duk_int_t label_id;
66184  duk_int_t label_catch_depth;
66185  duk_int_t label_pc; /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
66186  duk_bool_t label_is_closest;
66187 
66188  DUK_UNREF(res);
66189 
66190  duk__advance(comp_ctx); /* eat 'break' or 'continue' */
66191 
66192  if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
66193  comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
66194  comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
66195  /* break/continue without label */
66196 
66197  duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
66198  } else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
66199  /* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
66200  DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
66201  duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
66202  duk__advance(comp_ctx);
66203  } else {
66204  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
66205  }
66206 
66207  /* Use a fast break/continue when possible. A fast break/continue is
66208  * just a jump to the LABEL break/continue jump slot, which then jumps
66209  * to an appropriate place (for break, going through ENDLABEL correctly).
66210  * The peephole optimizer will optimize the jump to a direct one.
66211  */
66212 
66213  if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
66214  label_is_closest) {
66215  DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
66216  "label_catch_depth=%ld, catch_depth=%ld "
66217  "-> use fast variant (direct jump)",
66218  (long) is_break, (long) label_id, (long) label_is_closest,
66219  (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
66220 
66221  duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
66222  } else {
66223  DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
66224  "label_catch_depth=%ld, catch_depth=%ld "
66225  "-> use slow variant (longjmp)",
66226  (long) is_break, (long) label_id, (long) label_is_closest,
66227  (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
66228 
66229  duk__emit_bc(comp_ctx,
66230  is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
66231  (duk_regconst_t) label_id);
66232  }
66233 }
66234 
66235 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66236  duk_hthread *thr = comp_ctx->thr;
66237  duk_regconst_t rc_val;
66238 
66239  duk__advance(comp_ctx); /* eat 'return' */
66240 
66241  /* A 'return' statement is only allowed inside an actual function body,
66242  * not as part of eval or global code.
66243  */
66244  if (!comp_ctx->curr_func.is_function) {
66245  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
66246  }
66247 
66248  if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || /* explicit semi follows */
66249  comp_ctx->curr_token.lineterm || /* automatic semi will be inserted */
66250  comp_ctx->curr_token.allow_auto_semi) { /* automatic semi will be inserted */
66251  DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
66252  duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
66253  } else {
66254  duk_int_t pc_before_expr;
66255  duk_int_t pc_after_expr;
66256 
66257  DUK_DDD(DUK_DDDPRINT("return with a value"));
66258 
66259  DUK_UNREF(pc_before_expr);
66260  DUK_UNREF(pc_after_expr);
66261 
66262  pc_before_expr = duk__get_current_pc(comp_ctx);
66263  rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66264  pc_after_expr = duk__get_current_pc(comp_ctx);
66265 
66266  /* Tail call check: if last opcode emitted was CALL, and
66267  * the context allows it, change the CALL to TAILCALL.
66268  * This doesn't guarantee that a tail call will be allowed at
66269  * runtime, so the RETURN must still be emitted. (Duktape
66270  * 0.10.0 avoided this and simulated a RETURN if a tail call
66271  * couldn't be used at runtime; but this didn't work
66272  * correctly with a thread yield/resume, see
66273  * test-bug-tailcall-thread-yield-resume.js for discussion.)
66274  *
66275  * In addition to the last opcode being CALL, we also need to
66276  * be sure that 'rc_val' is the result register of the CALL.
66277  * For instance, for the expression 'return 0, (function ()
66278  * { return 1; }), 2' the last opcode emitted is CALL (no
66279  * bytecode is emitted for '2') but 'rc_val' indicates
66280  * constant '2'. Similarly if '2' is replaced by a register
66281  * bound variable, no opcodes are emitted but tail call would
66282  * be incorrect.
66283  *
66284  * This is tricky and easy to get wrong. It would be best to
66285  * track enough expression metadata to check that 'rc_val' came
66286  * from that last CALL instruction. We don't have that metadata
66287  * now, so we check that 'rc_val' is a temporary register result
66288  * (not a constant or a register bound variable). There should
66289  * be no way currently for 'rc_val' to be a temporary for an
66290  * expression following the CALL instruction without emitting
66291  * some opcodes following the CALL. This proxy check is used
66292  * below.
66293  *
66294  * See: test-bug-comma-expr-gh131.js.
66295  *
66296  * The non-standard 'caller' property disables tail calls
66297  * because they pose some special cases which haven't been
66298  * fixed yet.
66299  */
66300 
66301 #if defined(DUK_USE_TAILCALL)
66302  if (comp_ctx->curr_func.catch_depth == 0 && /* no catchers */
66303  pc_after_expr > pc_before_expr) { /* at least one opcode emitted */
66304  duk_compiler_instr *instr;
66305  duk_instr_t ins;
66306  duk_small_uint_t op;
66307 
66308  instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
66309  DUK_ASSERT(instr != NULL);
66310 
66311  ins = instr->ins;
66312  op = (duk_small_uint_t) DUK_DEC_OP(ins);
66313  if (op == DUK_OP_CALL &&
66314  DUK__ISTEMP(comp_ctx, rc_val) /* see above */) {
66315  DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
66316  "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
66317  "and last instruction is a CALL "
66318  "-> change to TAILCALL"));
66319  ins = (ins & ~DUK_BC_SHIFTED_MASK_OP) | (DUK_OP_TAILCALL << DUK_BC_SHIFT_OP);
66320  instr->ins = ins;
66321  }
66322  }
66323 #endif /* DUK_USE_TAILCALL */
66324 
66325  if (DUK__ISREG(rc_val)) {
66326  duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
66327  } else {
66328  rc_val = DUK__REMOVECONST(rc_val);
66329  if (duk__const_needs_refcount(comp_ctx, rc_val)) {
66330  duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
66331  } else {
66332  duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
66333  }
66334  }
66335  }
66336 }
66337 
66338 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66339  duk_reg_t reg_val;
66340 
66341  duk__advance(comp_ctx); /* eat 'throw' */
66342 
66343  /* Unlike break/continue, throw statement does not allow an empty value. */
66344 
66345  if (comp_ctx->curr_token.lineterm) {
66346  DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
66347  }
66348 
66349  reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66350  duk__emit_bc(comp_ctx,
66351  DUK_OP_THROW,
66352  (duk_regconst_t) reg_val);
66353 }
66354 
66355 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66356  duk_hthread *thr = comp_ctx->thr;
66357  duk_context *ctx = (duk_context *) thr;
66358  duk_reg_t reg_catch; /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
66359  duk_regconst_t rc_varname = 0;
66360  duk_small_uint_t trycatch_flags = 0;
66361  duk_int_t pc_ldconst = -1;
66362  duk_int_t pc_trycatch = -1;
66363  duk_int_t pc_catch = -1;
66364  duk_int_t pc_finally = -1;
66365 
66366  DUK_UNREF(res);
66367 
66368  /*
66369  * See the following documentation for discussion:
66370  *
66371  * doc/execution.rst: control flow details
66372  *
66373  * Try, catch, and finally "parts" are Blocks, not Statements, so
66374  * they must always be delimited by curly braces. This is unlike e.g.
66375  * the if statement, which accepts any Statement. This eliminates any
66376  * questions of matching parts of nested try statements. The Block
66377  * parsing is implemented inline here (instead of calling out).
66378  *
66379  * Finally part has a 'let scoped' variable, which requires a few kinks
66380  * here.
66381  */
66382 
66383  comp_ctx->curr_func.catch_depth++;
66384 
66385  duk__advance(comp_ctx); /* eat 'try' */
66386 
66387  reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
66388 
66389  /* The target for this LDCONST may need output shuffling, but we assume
66390  * that 'pc_ldconst' will be the LDCONST that we can patch later. This
66391  * should be the case because there's no input shuffling. (If there's
66392  * no catch clause, this LDCONST will be replaced with a NOP.)
66393  */
66394  pc_ldconst = duk__get_current_pc(comp_ctx);
66395  duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
66396 
66397  pc_trycatch = duk__get_current_pc(comp_ctx);
66398  duk__emit_invalid(comp_ctx); /* TRYCATCH, cannot emit now (not enough info) */
66399  duk__emit_invalid(comp_ctx); /* jump for 'catch' case */
66400  duk__emit_invalid(comp_ctx); /* jump for 'finally' case or end (if no finally) */
66401 
66402  /* try part */
66403  duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
66404  duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
66405  /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
66406  duk__emit_op_only(comp_ctx,
66407  DUK_OP_ENDTRY);
66408 
66409  if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
66410  /*
66411  * The catch variable must be updated to reflect the new allocated
66412  * register for the duration of the catch clause. We need to store
66413  * and restore the original value for the varmap entry (if any).
66414  */
66415 
66416  /*
66417  * Note: currently register bindings must be fixed for the entire
66418  * function. So, even though the catch variable is in a register
66419  * we know, we must use an explicit environment record and slow path
66420  * accesses to read/write the catch binding to make closures created
66421  * within the catch clause work correctly. This restriction should
66422  * be fixable (at least in common cases) later.
66423  *
66424  * See: test-bug-catch-binding-2.js.
66425  *
66426  * XXX: improve to get fast path access to most catch clauses.
66427  */
66428 
66429  duk_hstring *h_var;
66430  duk_int_t varmap_value; /* for storing/restoring the varmap binding for catch variable */
66431 
66432  DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(ctx)));
66433 
66434  trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
66435 
66436  pc_catch = duk__get_current_pc(comp_ctx);
66437 
66438  duk__advance(comp_ctx);
66439  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
66440 
66441  if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
66442  /* Identifier, i.e. don't allow reserved words */
66443  goto syntax_error;
66444  }
66445  h_var = comp_ctx->curr_token.str1;
66446  DUK_ASSERT(h_var != NULL);
66447 
66448  duk_push_hstring(ctx, h_var); /* keep in on valstack, use borrowed ref below */
66449 
66450  if (comp_ctx->curr_func.is_strict &&
66451  ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
66452  (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
66453  DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
66454  goto syntax_error;
66455  }
66456 
66457  duk_dup_top(ctx);
66458  rc_varname = duk__getconst(comp_ctx);
66459  DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
66460  (unsigned long) rc_varname, (long) rc_varname));
66461 
66462  duk__advance(comp_ctx);
66463  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
66464 
66465  duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
66466 
66467  DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
66468  (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
66469 
66470  duk_dup_top(ctx);
66471  duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
66472  if (duk_is_undefined(ctx, -1)) {
66473  varmap_value = -2;
66474  } else if (duk_is_null(ctx, -1)) {
66475  varmap_value = -1;
66476  } else {
66477  DUK_ASSERT(duk_is_number(ctx, -1));
66478  varmap_value = duk_get_int(ctx, -1);
66479  DUK_ASSERT(varmap_value >= 0);
66480  }
66481  duk_pop(ctx);
66482 
66483 #if 0
66484  /* It'd be nice to do something like this - but it doesn't
66485  * work for closures created inside the catch clause.
66486  */
66487  duk_dup_top(ctx);
66488  duk_push_int(ctx, (duk_int_t) (reg_catch + 0));
66489  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
66490 #endif
66491  duk_dup_top(ctx);
66492  duk_push_null(ctx);
66493  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
66494 
66495  duk__emit_a_bc(comp_ctx,
66496  DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
66497  (duk_regconst_t) (reg_catch + 0) /*value*/,
66498  rc_varname /*varname*/);
66499 
66500  DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
66501  (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
66502 
66503  duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
66504  /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
66505 
66506  if (varmap_value == -2) {
66507  /* not present */
66508  duk_del_prop(ctx, comp_ctx->curr_func.varmap_idx);
66509  } else {
66510  if (varmap_value == -1) {
66511  duk_push_null(ctx);
66512  } else {
66513  DUK_ASSERT(varmap_value >= 0);
66514  duk_push_int(ctx, varmap_value);
66515  }
66516  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx);
66517  }
66518  /* varname is popped by above code */
66519 
66520  DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
66521  (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx)));
66522 
66523  duk__emit_op_only(comp_ctx,
66524  DUK_OP_ENDCATCH);
66525 
66526  /*
66527  * XXX: for now, indicate that an expensive catch binding
66528  * declarative environment is always needed. If we don't
66529  * need it, we don't need the const_varname either.
66530  */
66531 
66532  trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
66533 
66534  DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(ctx)));
66535  }
66536 
66537  if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
66538  trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
66539 
66540  pc_finally = duk__get_current_pc(comp_ctx);
66541 
66542  duk__advance(comp_ctx);
66543 
66544  duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
66545  duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
66546  /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
66547  duk__emit_b(comp_ctx,
66548  DUK_OP_ENDFIN,
66549  reg_catch); /* rethrow */
66550  }
66551 
66552  if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
66553  !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
66554  /* must have catch and/or finally */
66555  goto syntax_error;
66556  }
66557 
66558  /* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
66559  * will replace the LDCONST with a NOP. For any actual constant (including
66560  * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
66561  */
66562 
66563  duk__patch_trycatch(comp_ctx,
66564  pc_ldconst,
66565  pc_trycatch,
66566  reg_catch,
66567  rc_varname,
66568  trycatch_flags);
66569 
66570  if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
66571  DUK_ASSERT(pc_catch >= 0);
66572  duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
66573  }
66574 
66575  if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
66576  DUK_ASSERT(pc_finally >= 0);
66577  duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
66578  } else {
66579  /* without finally, the second jump slot is used to jump to end of stmt */
66580  duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
66581  }
66582 
66583  comp_ctx->curr_func.catch_depth--;
66584  return;
66585 
66586  syntax_error:
66587  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
66588 }
66589 
66590 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
66591  duk_int_t pc_trycatch;
66592  duk_int_t pc_finished;
66593  duk_reg_t reg_catch;
66594  duk_small_uint_t trycatch_flags;
66595 
66596  if (comp_ctx->curr_func.is_strict) {
66597  DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
66598  }
66599 
66600  comp_ctx->curr_func.catch_depth++;
66601 
66602  duk__advance(comp_ctx); /* eat 'with' */
66603 
66604  reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
66605 
66606  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
66607  duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
66608  duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
66609 
66610  pc_trycatch = duk__get_current_pc(comp_ctx);
66611  trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
66612  duk__emit_a_bc(comp_ctx,
66613  DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
66614  (duk_regconst_t) trycatch_flags /*a*/,
66615  (duk_regconst_t) reg_catch /*bc*/);
66616  duk__emit_invalid(comp_ctx); /* catch jump */
66617  duk__emit_invalid(comp_ctx); /* finished jump */
66618 
66619  duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
66620  duk__emit_op_only(comp_ctx,
66621  DUK_OP_ENDTRY);
66622 
66623  pc_finished = duk__get_current_pc(comp_ctx);
66624 
66625  duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
66626 
66627  comp_ctx->curr_func.catch_depth--;
66628 }
66629 
66630 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
66631  /* if a site already exists, nop: max one label site per statement */
66632  if (label_id >= 0) {
66633  return label_id;
66634  }
66635 
66636  label_id = comp_ctx->curr_func.label_next++;
66637  DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
66638 
66639  duk__emit_bc(comp_ctx,
66640  DUK_OP_LABEL,
66641  (duk_regconst_t) label_id);
66642  duk__emit_invalid(comp_ctx);
66643  duk__emit_invalid(comp_ctx);
66644 
66645  return label_id;
66646 }
66647 
66648 /* Parse a single statement.
66649  *
66650  * Creates a label site (with an empty label) automatically for iteration
66651  * statements. Also "peels off" any label statements for explicit labels.
66652  */
66653 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
66654  duk_hthread *thr = comp_ctx->thr;
66655  duk_context *ctx = (duk_context *) thr;
66656  duk_bool_t dir_prol_at_entry; /* directive prologue status at entry */
66657  duk_reg_t temp_at_entry;
66658  duk_uarridx_t labels_len_at_entry;
66659  duk_int_t pc_at_entry; /* assumed to also be PC of "LABEL" */
66660  duk_int_t stmt_id;
66661  duk_small_uint_t stmt_flags = 0;
66662  duk_int_t label_id = -1;
66663  duk_small_uint_t tok;
66664 
66665  DUK__RECURSION_INCREASE(comp_ctx, thr);
66666 
66667  temp_at_entry = DUK__GETTEMP(comp_ctx);
66668  pc_at_entry = duk__get_current_pc(comp_ctx);
66669  labels_len_at_entry = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.labelnames_idx);
66670  stmt_id = comp_ctx->curr_func.stmt_next++;
66671  dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
66672 
66673  DUK_UNREF(stmt_id);
66674 
66675  DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
66676  "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
66677  (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
66678  (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
66679  (long) comp_ctx->curr_func.catch_depth));
66680 
66681  /* The directive prologue flag is cleared by default so that it is
66682  * unset for any recursive statement parsing. It is only "revived"
66683  * if a directive is detected. (We could also make directives only
66684  * allowed if 'allow_source_elem' was true.)
66685  */
66686  comp_ctx->curr_func.in_directive_prologue = 0;
66687 
66688  retry_parse:
66689 
66690  DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
66691  (long) stmt_id, (long) label_id, (long) allow_source_elem,
66692  (long) comp_ctx->curr_func.catch_depth));
66693 
66694  /*
66695  * Detect iteration statements; if encountered, establish an
66696  * empty label.
66697  */
66698 
66699  tok = comp_ctx->curr_token.t;
66700  if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
66701  tok == DUK_TOK_SWITCH) {
66702  DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
66703 
66704  label_id = duk__stmt_label_site(comp_ctx, label_id);
66705  duk__add_label(comp_ctx,
66706  DUK_HTHREAD_STRING_EMPTY_STRING(thr),
66707  pc_at_entry /*pc_label*/,
66708  label_id);
66709  }
66710 
66711  /*
66712  * Main switch for statement / source element type.
66713  */
66714 
66715  switch (comp_ctx->curr_token.t) {
66716  case DUK_TOK_FUNCTION: {
66717  /*
66718  * Function declaration, function expression, or (non-standard)
66719  * function statement.
66720  *
66721  * The E5 specification only allows function declarations at
66722  * the top level (in "source elements"). An ExpressionStatement
66723  * is explicitly not allowed to begin with a "function" keyword
66724  * (E5 Section 12.4). Hence any non-error semantics for such
66725  * non-top-level statements are non-standard. Duktape semantics
66726  * for function statements are modelled after V8, see
66727  * test-dev-func-decl-outside-top.js.
66728  */
66729 
66730 #if defined(DUK_USE_NONSTD_FUNC_STMT)
66731  /* Lenient: allow function declarations outside top level in
66732  * non-strict mode but reject them in strict mode.
66733  */
66734  if (allow_source_elem || !comp_ctx->curr_func.is_strict)
66735 #else /* DUK_USE_NONSTD_FUNC_STMT */
66736  /* Strict: never allow function declarations outside top level. */
66737  if (allow_source_elem)
66738 #endif /* DUK_USE_NONSTD_FUNC_STMT */
66739  {
66740  /* FunctionDeclaration: not strictly a statement but handled as such.
66741  *
66742  * O(depth^2) parse count for inner functions is handled by recording a
66743  * lexer offset on the first compilation pass, so that the function can
66744  * be efficiently skipped on the second pass. This is encapsulated into
66745  * duk__parse_func_like_fnum().
66746  */
66747 
66748  duk_int_t fnum;
66749 #if defined(DUK_USE_ASSERTIONS)
66750  duk_idx_t top_before;
66751 #endif
66752 
66753  DUK_DDD(DUK_DDDPRINT("function declaration statement"));
66754 
66755 #if defined(DUK_USE_ASSERTIONS)
66756  top_before = duk_get_top(ctx);
66757 #endif
66758 
66759  duk__advance(comp_ctx); /* eat 'function' */
66760  fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
66761 
66762  /* The value stack convention here is a bit odd: the function
66763  * name is only pushed on pass 1 (in_scanning), and is needed
66764  * to process function declarations.
66765  */
66766  if (comp_ctx->curr_func.in_scanning) {
66767  duk_uarridx_t n;
66768 
66769 #if defined(DUK_USE_ASSERTIONS)
66770  DUK_ASSERT(duk_get_top(ctx) == top_before + 1);
66771 #endif
66772  DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
66773  duk_get_tval(ctx, -1), (long) fnum));
66774  n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
66775  /* funcname is at index -1 */
66776  duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n);
66777  duk_push_int(ctx, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
66778  duk_put_prop_index(ctx, comp_ctx->curr_func.decls_idx, n + 1);
66779  } else {
66780 #if defined(DUK_USE_ASSERTIONS)
66781  DUK_ASSERT(duk_get_top(ctx) == top_before);
66782 #endif
66783  }
66784 
66785  /* no statement value (unlike function expression) */
66786  stmt_flags = 0;
66787  break;
66788  } else {
66789  DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
66790  }
66791  break;
66792  }
66793  case DUK_TOK_LCURLY: {
66794  DUK_DDD(DUK_DDDPRINT("block statement"));
66795  duk__advance(comp_ctx);
66796  duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);
66797  /* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
66798  if (label_id >= 0) {
66799  duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
66800  }
66801  stmt_flags = 0;
66802  break;
66803  }
66804  case DUK_TOK_CONST: {
66805  DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
66806  duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
66807  stmt_flags = DUK__HAS_TERM;
66808  break;
66809  }
66810  case DUK_TOK_VAR: {
66811  DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
66812  duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
66813  stmt_flags = DUK__HAS_TERM;
66814  break;
66815  }
66816  case DUK_TOK_SEMICOLON: {
66817  /* empty statement with an explicit semicolon */
66818  DUK_DDD(DUK_DDDPRINT("empty statement"));
66819  stmt_flags = DUK__HAS_TERM;
66820  break;
66821  }
66822  case DUK_TOK_IF: {
66823  DUK_DDD(DUK_DDDPRINT("if statement"));
66824  duk__parse_if_stmt(comp_ctx, res);
66825  if (label_id >= 0) {
66826  duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
66827  }
66828  stmt_flags = 0;
66829  break;
66830  }
66831  case DUK_TOK_DO: {
66832  /*
66833  * Do-while statement is mostly trivial, but there is special
66834  * handling for automatic semicolon handling (triggered by the
66835  * DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
66836  *
66837  * https://bugs.ecmascript.org/show_bug.cgi?id=8
66838  *
66839  * See doc/compiler.rst for details.
66840  */
66841  DUK_DDD(DUK_DDDPRINT("do statement"));
66842  DUK_ASSERT(label_id >= 0);
66843  duk__update_label_flags(comp_ctx,
66844  label_id,
66845  DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
66846  duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
66847  stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS; /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
66848  break;
66849  }
66850  case DUK_TOK_WHILE: {
66851  DUK_DDD(DUK_DDDPRINT("while statement"));
66852  DUK_ASSERT(label_id >= 0);
66853  duk__update_label_flags(comp_ctx,
66854  label_id,
66855  DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
66856  duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
66857  stmt_flags = 0;
66858  break;
66859  }
66860  case DUK_TOK_FOR: {
66861  /*
66862  * For/for-in statement is complicated to parse because
66863  * determining the statement type (three-part for vs. a
66864  * for-in) requires potential backtracking.
66865  *
66866  * See the helper for the messy stuff.
66867  */
66868  DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
66869  DUK_ASSERT(label_id >= 0);
66870  duk__update_label_flags(comp_ctx,
66871  label_id,
66872  DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
66873  duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
66874  stmt_flags = 0;
66875  break;
66876  }
66877  case DUK_TOK_CONTINUE:
66878  case DUK_TOK_BREAK: {
66879  DUK_DDD(DUK_DDDPRINT("break/continue statement"));
66880  duk__parse_break_or_continue_stmt(comp_ctx, res);
66881  stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
66882  break;
66883  }
66884  case DUK_TOK_RETURN: {
66885  DUK_DDD(DUK_DDDPRINT("return statement"));
66886  duk__parse_return_stmt(comp_ctx, res);
66887  stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
66888  break;
66889  }
66890  case DUK_TOK_WITH: {
66891  DUK_DDD(DUK_DDDPRINT("with statement"));
66892  comp_ctx->curr_func.with_depth++;
66893  duk__parse_with_stmt(comp_ctx, res);
66894  if (label_id >= 0) {
66895  duk__patch_jump_here(comp_ctx, pc_at_entry + 1); /* break jump */
66896  }
66897  comp_ctx->curr_func.with_depth--;
66898  stmt_flags = 0;
66899  break;
66900  }
66901  case DUK_TOK_SWITCH: {
66902  /*
66903  * The switch statement is pretty messy to compile.
66904  * See the helper for details.
66905  */
66906  DUK_DDD(DUK_DDDPRINT("switch statement"));
66907  DUK_ASSERT(label_id >= 0);
66908  duk__update_label_flags(comp_ctx,
66909  label_id,
66910  DUK_LABEL_FLAG_ALLOW_BREAK); /* don't allow continue */
66911  duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
66912  stmt_flags = 0;
66913  break;
66914  }
66915  case DUK_TOK_THROW: {
66916  DUK_DDD(DUK_DDDPRINT("throw statement"));
66917  duk__parse_throw_stmt(comp_ctx, res);
66918  stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
66919  break;
66920  }
66921  case DUK_TOK_TRY: {
66922  DUK_DDD(DUK_DDDPRINT("try statement"));
66923  duk__parse_try_stmt(comp_ctx, res);
66924  stmt_flags = 0;
66925  break;
66926  }
66927  case DUK_TOK_DEBUGGER: {
66928  duk__advance(comp_ctx);
66929 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66930  DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
66931  duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
66932 #else
66933  DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
66934 #endif
66935  stmt_flags = DUK__HAS_TERM;
66936  break;
66937  }
66938  default: {
66939  /*
66940  * Else, must be one of:
66941  * - ExpressionStatement, possibly a directive (String)
66942  * - LabelledStatement (Identifier followed by ':')
66943  *
66944  * Expressions beginning with 'function' keyword are covered by a case
66945  * above (such expressions are not allowed in standard E5 anyway).
66946  * Also expressions starting with '{' are interpreted as block
66947  * statements. See E5 Section 12.4.
66948  *
66949  * Directive detection is tricky; see E5 Section 14.1 on directive
66950  * prologue. A directive is an expression statement with a single
66951  * string literal and an explicit or automatic semicolon. Escape
66952  * characters are significant and no parens etc are allowed:
66953  *
66954  * 'use strict'; // valid 'use strict' directive
66955  * 'use\u0020strict'; // valid directive, not a 'use strict' directive
66956  * ('use strict'); // not a valid directive
66957  *
66958  * The expression is determined to consist of a single string literal
66959  * based on duk__expr_nud() and duk__expr_led() call counts. The string literal
66960  * of a 'use strict' directive is determined to lack any escapes based
66961  * num_escapes count from the lexer. Note that other directives may be
66962  * allowed to contain escapes, so a directive with escapes does not
66963  * terminate a directive prologue.
66964  *
66965  * We rely on the fact that the expression parser will not emit any
66966  * code for a single token expression. However, it will generate an
66967  * intermediate value which we will then successfully ignore.
66968  *
66969  * A similar approach is used for labels.
66970  */
66971 
66972  duk_bool_t single_token;
66973 
66974  DUK_DDD(DUK_DDDPRINT("expression statement"));
66975  duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
66976 
66977  single_token = (comp_ctx->curr_func.nud_count == 1 && /* one token */
66978  comp_ctx->curr_func.led_count == 0); /* no operators */
66979 
66980  if (single_token &&
66981  comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
66982  comp_ctx->curr_token.t == DUK_TOK_COLON) {
66983  /*
66984  * Detected label
66985  */
66986 
66987  duk_hstring *h_lab;
66988 
66989  /* expected ival */
66990  DUK_ASSERT(res->t == DUK_IVAL_VAR);
66991  DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
66992  DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(ctx, res->x1.valstack_idx)));
66993  h_lab = comp_ctx->prev_token.str1;
66994  DUK_ASSERT(h_lab != NULL);
66995 
66996  DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
66997  (duk_heaphdr *) h_lab));
66998 
66999  duk__advance(comp_ctx); /* eat colon */
67000 
67001  label_id = duk__stmt_label_site(comp_ctx, label_id);
67002 
67003  duk__add_label(comp_ctx,
67004  h_lab,
67005  pc_at_entry /*pc_label*/,
67006  label_id);
67007 
67008  /* a statement following a label cannot be a source element
67009  * (a function declaration).
67010  */
67011  allow_source_elem = 0;
67012 
67013  DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
67014  goto retry_parse;
67015  }
67016 
67017  stmt_flags = 0;
67018 
67019  if (dir_prol_at_entry && /* still in prologue */
67020  single_token && /* single string token */
67021  comp_ctx->prev_token.t == DUK_TOK_STRING) {
67022  /*
67023  * Detected a directive
67024  */
67025  duk_hstring *h_dir;
67026 
67027  /* expected ival */
67028  DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
67029  DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
67030  DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(ctx, res->x1.valstack_idx)));
67031  h_dir = comp_ctx->prev_token.str1;
67032  DUK_ASSERT(h_dir != NULL);
67033 
67034  DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
67035 
67036  stmt_flags |= DUK__STILL_PROLOGUE;
67037 
67038  /* Note: escaped characters differentiate directives */
67039 
67040  if (comp_ctx->prev_token.num_escapes > 0) {
67041  DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
67042  "but we ignore such directives"));
67043  } else {
67044  /*
67045  * The length comparisons are present to handle
67046  * strings like "use strict\u0000foo" as required.
67047  */
67048 
67049  if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
67050  DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict", 10) == 0) {
67051 #if defined(DUK_USE_STRICT_DECL)
67052  DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
67053  (long) comp_ctx->curr_func.is_strict, (long) 1));
67054  comp_ctx->curr_func.is_strict = 1;
67055 #else
67056  DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
67057 #endif
67058  } else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
67059  DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail", 14) == 0) {
67060  DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
67061  (long) comp_ctx->curr_func.is_notail, (long) 1));
67062  comp_ctx->curr_func.is_notail = 1;
67063  } else {
67064  DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
67065  "directive prologue", (duk_hobject *) h_dir));
67066  }
67067  }
67068  } else {
67069  DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
67070  "prologue terminated if still active"));
67071  }
67072 
67073  stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
67074  }
67075  } /* end switch (tok) */
67076 
67077  /*
67078  * Statement value handling.
67079  *
67080  * Global code and eval code has an implicit return value
67081  * which comes from the last statement with a value
67082  * (technically a non-"empty" continuation, which is
67083  * different from an empty statement).
67084  *
67085  * Since we don't know whether a later statement will
67086  * override the value of the current statement, we need
67087  * to coerce the statement value to a register allocated
67088  * for implicit return values. In other cases we need
67089  * to coerce the statement value to a plain value to get
67090  * any side effects out (consider e.g. "foo.bar;").
67091  */
67092 
67093  /* XXX: what about statements which leave a half-cooked value in 'res'
67094  * but have no stmt value? Any such statements?
67095  */
67096 
67097  if (stmt_flags & DUK__HAS_VAL) {
67098  duk_reg_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
67099  if (reg_stmt_value >= 0) {
67100  duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
67101  } else {
67102  duk__ivalue_toplain_ignore(comp_ctx, res);
67103  }
67104  } else {
67105  ;
67106  }
67107 
67108  /*
67109  * Statement terminator check, including automatic semicolon
67110  * handling. After this step, 'curr_tok' should be the first
67111  * token after a possible statement terminator.
67112  */
67113 
67114  if (stmt_flags & DUK__HAS_TERM) {
67115  if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
67116  DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
67117  duk__advance(comp_ctx);
67118  } else {
67119  if (comp_ctx->curr_token.allow_auto_semi) {
67120  DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
67121  } else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
67122  /* XXX: make this lenience dependent on flags or strictness? */
67123  DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
67124  "even though no lineterm present before next token)"));
67125  } else {
67126  DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
67127  }
67128  }
67129  } else {
67130  DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
67131  }
67132 
67133  /*
67134  * Directive prologue tracking.
67135  */
67136 
67137  if (stmt_flags & DUK__STILL_PROLOGUE) {
67138  DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
67139  comp_ctx->curr_func.in_directive_prologue = 1;
67140  }
67141 
67142  /*
67143  * Cleanups (all statement parsing flows through here).
67144  *
67145  * Pop label site and reset labels. Reset 'next temp' to value at
67146  * entry to reuse temps.
67147  */
67148 
67149  if (label_id >= 0) {
67150  duk__emit_bc(comp_ctx,
67151  DUK_OP_ENDLABEL,
67152  (duk_regconst_t) label_id);
67153  }
67154 
67155  DUK__SETTEMP(comp_ctx, temp_at_entry);
67156 
67157  duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
67158 
67159  /* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
67160 
67161  DUK__RECURSION_DECREASE(comp_ctx, thr);
67162 }
67163 
67164 /*
67165  * Parse a statement list.
67166  *
67167  * Handles automatic semicolon insertion and implicit return value.
67168  *
67169  * Upon entry, 'curr_tok' should contain the first token of the first
67170  * statement (parsed in the "allow regexp literal" mode). Upon exit,
67171  * 'curr_tok' contains the token following the statement list terminator
67172  * (EOF or closing brace).
67173  */
67174 
67175 DUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {
67176  duk_hthread *thr = comp_ctx->thr;
67177  duk_context *ctx = (duk_context *) thr;
67178  duk_ivalue res_alloc;
67179  duk_ivalue *res = &res_alloc;
67180 
67181  /* Setup state. Initial ivalue is 'undefined'. */
67182 
67183  duk_require_stack(ctx, DUK__PARSE_STATEMENTS_SLOTS);
67184 
67185  /* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
67186  * intermediate values suffice for parsing of each function. Nesting is needed
67187  * for nested functions (which may occur inside expressions).
67188  */
67189 
67190  DUK_MEMZERO(&res_alloc, sizeof(res_alloc));
67191  res->t = DUK_IVAL_PLAIN;
67192  res->x1.t = DUK_ISPEC_VALUE;
67193  res->x1.valstack_idx = duk_get_top(ctx);
67194  res->x2.valstack_idx = res->x1.valstack_idx + 1;
67195  duk_push_undefined(ctx);
67196  duk_push_undefined(ctx);
67197 
67198  /* Parse statements until a closing token (EOF or '}') is found. */
67199 
67200  for (;;) {
67201  /* Check whether statement list ends. */
67202 
67203  if (expect_eof) {
67204  if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
67205  break;
67206  }
67207  } else {
67208  if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
67209  break;
67210  }
67211  }
67212 
67213  /* Check statement type based on the first token type.
67214  *
67215  * Note: expression parsing helpers expect 'curr_tok' to
67216  * contain the first token of the expression upon entry.
67217  */
67218 
67219  DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
67220 
67221  duk__parse_stmt(comp_ctx, res, allow_source_elem);
67222  }
67223 
67224  duk__advance(comp_ctx);
67225 
67226  /* Tear down state. */
67227 
67228  duk_pop_2(ctx);
67229 }
67230 
67231 /*
67232  * Declaration binding instantiation conceptually happens when calling a
67233  * function; for us it essentially means that function prologue. The
67234  * conceptual process is described in E5 Section 10.5.
67235  *
67236  * We need to keep track of all encountered identifiers to (1) create an
67237  * identifier-to-register map ("varmap"); and (2) detect duplicate
67238  * declarations. Identifiers which are not bound to registers still need
67239  * to be tracked for detecting duplicates. Currently such identifiers
67240  * are put into the varmap with a 'null' value, which is later cleaned up.
67241  *
67242  * To support functions with a large number of variable and function
67243  * declarations, registers are not allocated beyond a certain limit;
67244  * after that limit, variables and functions need slow path access.
67245  * Arguments are currently always register bound, which imposes a hard
67246  * (and relatively small) argument count limit.
67247  *
67248  * Some bindings in E5 are not configurable (= deletable) and almost all
67249  * are mutable (writable). Exceptions are:
67250  *
67251  * - The 'arguments' binding, established only if no shadowing argument
67252  * or function declaration exists. We handle 'arguments' creation
67253  * and binding through an explicit slow path environment record.
67254  *
67255  * - The "name" binding for a named function expression. This is also
67256  * handled through an explicit slow path environment record.
67257  */
67258 
67259 /* XXX: add support for variables to not be register bound always, to
67260  * handle cases with a very large number of variables?
67261  */
67262 
67263 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_reg_t *out_stmt_value_reg) {
67264  duk_hthread *thr = comp_ctx->thr;
67265  duk_context *ctx = (duk_context *) thr;
67266  duk_hstring *h_name;
67267  duk_bool_t configurable_bindings;
67268  duk_uarridx_t num_args;
67269  duk_uarridx_t num_decls;
67270  duk_regconst_t rc_name;
67271  duk_small_uint_t declvar_flags;
67272  duk_uarridx_t i;
67273 #if defined(DUK_USE_ASSERTIONS)
67274  duk_idx_t entry_top;
67275 #endif
67276 
67277 #if defined(DUK_USE_ASSERTIONS)
67278  entry_top = duk_get_top(ctx);
67279 #endif
67280 
67281  /*
67282  * Preliminaries
67283  */
67284 
67285  configurable_bindings = comp_ctx->curr_func.is_eval;
67286  DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
67287 
67288  /* varmap is already in comp_ctx->curr_func.varmap_idx */
67289 
67290  /*
67291  * Function formal arguments, always bound to registers
67292  * (there's no support for shuffling them now).
67293  */
67294 
67295  num_args = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
67296  DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
67297  /* XXX: check num_args */
67298 
67299  for (i = 0; i < num_args; i++) {
67300  duk_get_prop_index(ctx, comp_ctx->curr_func.argnames_idx, i);
67301  h_name = duk_known_hstring(ctx, -1);
67302 
67303  if (comp_ctx->curr_func.is_strict) {
67304  if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
67305  DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
67306  goto error_argname;
67307  }
67308  duk_dup_top(ctx);
67309  if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
67310  DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
67311  goto error_argname;
67312  }
67313 
67314  /* Ensure argument name is not a reserved word in current
67315  * (final) strictness. Formal argument parsing may not
67316  * catch reserved names if strictness changes during
67317  * parsing.
67318  *
67319  * We only need to do this in strict mode because non-strict
67320  * keyword are always detected in formal argument parsing.
67321  */
67322 
67323  if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
67324  goto error_argname;
67325  }
67326  }
67327 
67328  /* overwrite any previous binding of the same name; the effect is
67329  * that last argument of a certain name wins.
67330  */
67331 
67332  /* only functions can have arguments */
67333  DUK_ASSERT(comp_ctx->curr_func.is_function);
67334  duk_push_uarridx(ctx, i); /* -> [ ... name index ] */
67335  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
67336 
67337  /* no code needs to be emitted, the regs already have values */
67338  }
67339 
67340  /* use temp_next for tracking register allocations */
67341  DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_reg_t) num_args);
67342 
67343  /*
67344  * After arguments, allocate special registers (like shuffling temps)
67345  */
67346 
67347  if (out_stmt_value_reg) {
67348  *out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
67349  }
67350  if (comp_ctx->curr_func.needs_shuffle) {
67351  duk_reg_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
67352  comp_ctx->curr_func.shuffle1 = shuffle_base;
67353  comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
67354  comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
67355  DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
67356  (long) comp_ctx->curr_func.shuffle1,
67357  (long) comp_ctx->curr_func.shuffle2,
67358  (long) comp_ctx->curr_func.shuffle3));
67359  }
67360  if (comp_ctx->curr_func.temp_next > 0x100) {
67361  DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
67362  goto error_outofregs;
67363  }
67364 
67365  /*
67366  * Function declarations
67367  */
67368 
67369  num_decls = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.decls_idx);
67370  DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
67371  (long) num_decls,
67372  (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.decls_idx)));
67373  for (i = 0; i < num_decls; i += 2) {
67374  duk_int_t decl_type;
67375  duk_int_t fnum;
67376 
67377  duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
67378  decl_type = duk_to_int(ctx, -1);
67379  fnum = decl_type >> 8; /* XXX: macros */
67380  decl_type = decl_type & 0xff;
67381  duk_pop(ctx);
67382 
67383  if (decl_type != DUK_DECL_TYPE_FUNC) {
67384  continue;
67385  }
67386 
67387  duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
67388 
67389  /* XXX: spilling */
67390  if (comp_ctx->curr_func.is_function) {
67391  duk_reg_t reg_bind;
67392  duk_dup_top(ctx);
67393  if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
67394  /* shadowed; update value */
67395  duk_dup_top(ctx);
67396  duk_get_prop(ctx, comp_ctx->curr_func.varmap_idx);
67397  reg_bind = duk_to_int(ctx, -1); /* [ ... name reg_bind ] */
67398  duk__emit_a_bc(comp_ctx,
67399  DUK_OP_CLOSURE,
67400  (duk_regconst_t) reg_bind,
67401  (duk_regconst_t) fnum);
67402  } else {
67403  /* function: always register bound */
67404  reg_bind = DUK__ALLOCTEMP(comp_ctx);
67405  duk__emit_a_bc(comp_ctx,
67406  DUK_OP_CLOSURE,
67407  (duk_regconst_t) reg_bind,
67408  (duk_regconst_t) fnum);
67409  duk_push_int(ctx, (duk_int_t) reg_bind);
67410  }
67411  } else {
67412  /* Function declaration for global/eval code is emitted even
67413  * for duplicates, because of E5 Section 10.5, step 5.e of
67414  * E5.1 (special behavior for variable bound to global object).
67415  *
67416  * DECLVAR will not re-declare a variable as such, but will
67417  * update the binding value.
67418  */
67419 
67420  duk_reg_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
67421  duk_dup_top(ctx);
67422  rc_name = duk__getconst(comp_ctx);
67423  duk_push_null(ctx);
67424 
67425  duk__emit_a_bc(comp_ctx,
67426  DUK_OP_CLOSURE,
67427  (duk_regconst_t) reg_temp,
67428  (duk_regconst_t) fnum);
67429 
67430  declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
67431  DUK_PROPDESC_FLAG_ENUMERABLE |
67432  DUK_BC_DECLVAR_FLAG_FUNC_DECL;
67433 
67434  if (configurable_bindings) {
67435  declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
67436  }
67437 
67438  duk__emit_a_b_c(comp_ctx,
67439  DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
67440  (duk_regconst_t) declvar_flags /*flags*/,
67441  rc_name /*name*/,
67442  (duk_regconst_t) reg_temp /*value*/);
67443 
67444  DUK__SETTEMP(comp_ctx, reg_temp); /* forget temp */
67445  }
67446 
67447  DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
67448  (duk_tval *) duk_get_tval(ctx, -2),
67449  (duk_tval *) duk_get_tval(ctx, -1)));
67450 
67451  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
67452  }
67453 
67454  /*
67455  * 'arguments' binding is special; if a shadowing argument or
67456  * function declaration exists, an arguments object will
67457  * definitely not be needed, regardless of whether the identifier
67458  * 'arguments' is referenced inside the function body.
67459  */
67460 
67461  if (duk_has_prop_stridx(ctx, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
67462  DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
67463  "-> arguments object creation can be skipped"));
67464  comp_ctx->curr_func.is_arguments_shadowed = 1;
67465  }
67466 
67467  /*
67468  * Variable declarations.
67469  *
67470  * Unlike function declarations, variable declaration values don't get
67471  * assigned on entry. If a binding of the same name already exists, just
67472  * ignore it silently.
67473  */
67474 
67475  for (i = 0; i < num_decls; i += 2) {
67476  duk_int_t decl_type;
67477 
67478  duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i + 1); /* decl type */
67479  decl_type = duk_to_int(ctx, -1);
67480  decl_type = decl_type & 0xff;
67481  duk_pop(ctx);
67482 
67483  if (decl_type != DUK_DECL_TYPE_VAR) {
67484  continue;
67485  }
67486 
67487  duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
67488 
67489  if (duk_has_prop(ctx, comp_ctx->curr_func.varmap_idx)) {
67490  /* shadowed, ignore */
67491  } else {
67492  duk_get_prop_index(ctx, comp_ctx->curr_func.decls_idx, i); /* decl name */
67493  h_name = duk_known_hstring(ctx, -1);
67494 
67495  if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
67496  !comp_ctx->curr_func.is_arguments_shadowed) {
67497  /* E5 Section steps 7-8 */
67498  DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
67499  "but appears as a variable declaration -> treat as "
67500  "a no-op for variable declaration purposes"));
67501  duk_pop(ctx);
67502  continue;
67503  }
67504 
67505  /* XXX: spilling */
67506  if (comp_ctx->curr_func.is_function) {
67507  duk_reg_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
67508  /* no need to init reg, it will be undefined on entry */
67509  duk_push_int(ctx, (duk_int_t) reg_bind);
67510  } else {
67511  duk_dup_top(ctx);
67512  rc_name = duk__getconst(comp_ctx);
67513  duk_push_null(ctx);
67514 
67515  declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
67516  DUK_PROPDESC_FLAG_ENUMERABLE |
67517  DUK_BC_DECLVAR_FLAG_UNDEF_VALUE;
67518  if (configurable_bindings) {
67519  declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
67520  }
67521 
67522  duk__emit_a_b_c(comp_ctx,
67523  DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
67524  (duk_regconst_t) declvar_flags /*flags*/,
67525  rc_name /*name*/,
67526  (duk_regconst_t) 0 /*value*/);
67527  }
67528 
67529  duk_put_prop(ctx, comp_ctx->curr_func.varmap_idx); /* [ ... name reg/null ] -> [ ... ] */
67530  }
67531  }
67532 
67533  /*
67534  * Wrap up
67535  */
67536 
67537  DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
67538  (duk_tval *) duk_get_tval(ctx, comp_ctx->curr_func.varmap_idx),
67539  (long) comp_ctx->curr_func.is_arguments_shadowed));
67540 
67541  DUK_ASSERT_TOP(ctx, entry_top);
67542  return;
67543 
67544  error_outofregs:
67545  DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
67546  DUK_UNREACHABLE();
67547  return;
67548 
67549  error_argname:
67550  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
67551  DUK_UNREACHABLE();
67552  return;
67553 }
67554 
67555 /*
67556  * Parse a function-body-like expression (FunctionBody or Program
67557  * in E5 grammar) using a two-pass parse. The productions appear
67558  * in the following contexts:
67559  *
67560  * - function expression
67561  * - function statement
67562  * - function declaration
67563  * - getter in object literal
67564  * - setter in object literal
67565  * - global code
67566  * - eval code
67567  * - Function constructor body
67568  *
67569  * This function only parses the statement list of the body; the argument
67570  * list and possible function name must be initialized by the caller.
67571  * For instance, for Function constructor, the argument names are originally
67572  * on the value stack. The parsing of statements ends either at an EOF or
67573  * a closing brace; this is controlled by an input flag.
67574  *
67575  * Note that there are many differences affecting parsing and even code
67576  * generation:
67577  *
67578  * - Global and eval code have an implicit return value generated
67579  * by the last statement; function code does not
67580  *
67581  * - Global code, eval code, and Function constructor body end in
67582  * an EOF, other bodies in a closing brace ('}')
67583  *
67584  * Upon entry, 'curr_tok' is ignored and the function will pull in the
67585  * first token on its own. Upon exit, 'curr_tok' is the terminating
67586  * token (EOF or closing brace).
67587  */
67588 
67589 DUK_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) {
67590  duk_compiler_func *func;
67591  duk_hthread *thr;
67592  duk_context *ctx;
67593  duk_reg_t reg_stmt_value = -1;
67594  duk_lexer_point lex_pt;
67595  duk_reg_t temp_first;
67596  duk_small_int_t compile_round = 1;
67597 
67598  DUK_ASSERT(comp_ctx != NULL);
67599 
67600  thr = comp_ctx->thr;
67601  ctx = (duk_context *) thr;
67602  DUK_ASSERT(thr != NULL);
67603 
67604  func = &comp_ctx->curr_func;
67605  DUK_ASSERT(func != NULL);
67606 
67607  DUK__RECURSION_INCREASE(comp_ctx, thr);
67608 
67609  duk_require_stack(ctx, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
67610 
67611  /*
67612  * Store lexer position for a later rewind
67613  */
67614 
67615  DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
67616 
67617  /*
67618  * Program code (global and eval code) has an implicit return value
67619  * from the last statement value (e.g. eval("1; 2+3;") returns 3).
67620  * This is not the case with functions. If implicit statement return
67621  * value is requested, all statements are coerced to a register
67622  * allocated here, and used in the implicit return statement below.
67623  */
67624 
67625  /* XXX: this is pointless here because pass 1 is throw-away */
67626  if (implicit_return_value) {
67627  reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
67628 
67629  /* If an implicit return value is needed by caller, it must be
67630  * initialized to 'undefined' because we don't know whether any
67631  * non-empty (where "empty" is a continuation type, and different
67632  * from an empty statement) statements will be executed.
67633  *
67634  * However, since 1st pass is a throwaway one, no need to emit
67635  * it here.
67636  */
67637 #if 0
67638  duk__emit_bc(comp_ctx,
67639  DUK_OP_LDUNDEF,
67640  0);
67641 #endif
67642  }
67643 
67644  /*
67645  * First pass.
67646  *
67647  * Gather variable/function declarations needed for second pass.
67648  * Code generated is dummy and discarded.
67649  */
67650 
67651  func->in_directive_prologue = 1;
67652  func->in_scanning = 1;
67653  func->may_direct_eval = 0;
67654  func->id_access_arguments = 0;
67655  func->id_access_slow = 0;
67656  func->id_access_slow_own = 0;
67657  func->reg_stmt_value = reg_stmt_value;
67658 #if defined(DUK_USE_DEBUGGER_SUPPORT)
67659  func->min_line = DUK_INT_MAX;
67660  func->max_line = 0;
67661 #endif
67662 
67663  /* duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp literal" mode with current strictness */
67664  if (expect_token >= 0) {
67665  /* Eating a left curly; regexp mode is allowed by left curly
67666  * based on duk__token_lbp[] automatically.
67667  */
67668  DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
67669  duk__update_lineinfo_currtoken(comp_ctx);
67670  duk__advance_expect(comp_ctx, expect_token);
67671  } else {
67672  /* Need to set curr_token.t because lexing regexp mode depends on current
67673  * token type. Zero value causes "allow regexp" mode.
67674  */
67675  comp_ctx->curr_token.t = 0;
67676  duk__advance(comp_ctx);
67677  }
67678 
67679  DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
67680  duk__parse_stmts(comp_ctx,
67681  1, /* allow source elements */
67682  expect_eof); /* expect EOF instead of } */
67683  DUK_DDD(DUK_DDDPRINT("end 1st pass"));
67684 
67685  /*
67686  * Second (and possibly third) pass.
67687  *
67688  * Generate actual code. In most cases the need for shuffle
67689  * registers is detected during pass 1, but in some corner cases
67690  * we'll only detect it during pass 2 and a third pass is then
67691  * needed (see GH-115).
67692  */
67693 
67694  for (;;) {
67695  duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
67696  compile_round++;
67697 
67698  /*
67699  * Rewind lexer.
67700  *
67701  * duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
67702  * literal" mode with current strictness.
67703  *
67704  * curr_token line number info should be initialized for pass 2 before
67705  * generating prologue, to ensure prologue bytecode gets nice line numbers.
67706  */
67707 
67708  DUK_DDD(DUK_DDDPRINT("rewind lexer"));
67709  DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
67710  comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
67711  comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
67712  duk__advance(comp_ctx);
67713 
67714  /*
67715  * Reset function state and perform register allocation, which creates
67716  * 'varmap' for second pass. Function prologue for variable declarations,
67717  * binding value initializations etc is emitted as a by-product.
67718  *
67719  * Strict mode restrictions for duplicate and invalid argument
67720  * names are checked here now that we know whether the function
67721  * is actually strict. See: test-dev-strict-mode-boundary.js.
67722  *
67723  * Inner functions are compiled during pass 1 and are not reset.
67724  */
67725 
67726  duk__reset_func_for_pass2(comp_ctx);
67727  func->in_directive_prologue = 1;
67728  func->in_scanning = 0;
67729 
67730  /* must be able to emit code, alloc consts, etc. */
67731 
67732  duk__init_varmap_and_prologue_for_pass2(comp_ctx,
67733  (implicit_return_value ? &reg_stmt_value : NULL));
67734  func->reg_stmt_value = reg_stmt_value;
67735 
67736  temp_first = DUK__GETTEMP(comp_ctx);
67737 
67738  func->temp_first = temp_first;
67739  func->temp_next = temp_first;
67740  func->stmt_next = 0;
67741  func->label_next = 0;
67742 
67743  /* XXX: init or assert catch depth etc -- all values */
67744  func->id_access_arguments = 0;
67745  func->id_access_slow = 0;
67746  func->id_access_slow_own = 0;
67747 
67748  /*
67749  * Check function name validity now that we know strictness.
67750  * This only applies to function declarations and expressions,
67751  * not setter/getter name.
67752  *
67753  * See: test-dev-strict-mode-boundary.js
67754  */
67755 
67756  if (func->is_function && !func->is_setget && func->h_name != NULL) {
67757  if (func->is_strict) {
67758  if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
67759  DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
67760  goto error_funcname;
67761  }
67762  if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
67763  DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
67764  goto error_funcname;
67765  }
67766  } else {
67767  if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
67768  !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
67769  DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
67770  goto error_funcname;
67771  }
67772  }
67773  }
67774 
67775  /*
67776  * Second pass parsing.
67777  */
67778 
67779  if (implicit_return_value) {
67780  /* Default implicit return value. */
67781  duk__emit_bc(comp_ctx,
67782  DUK_OP_LDUNDEF,
67783  0);
67784  }
67785 
67786  DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
67787  duk__parse_stmts(comp_ctx,
67788  1, /* allow source elements */
67789  expect_eof); /* expect EOF instead of } */
67790  DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
67791 
67792  duk__update_lineinfo_currtoken(comp_ctx);
67793 
67794  if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
67795  /* Shuffle decision not changed. */
67796  break;
67797  }
67798  if (compile_round >= 3) {
67799  /* Should never happen but avoid infinite loop just in case. */
67800  DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
67801  DUK_ERROR_INTERNAL(thr);
67802  }
67803  DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
67804  }
67805 
67806  /*
67807  * Emit a final RETURN.
67808  *
67809  * It would be nice to avoid emitting an unnecessary "return" opcode
67810  * if the current PC is not reachable. However, this cannot be reliably
67811  * detected; even if the previous instruction is an unconditional jump,
67812  * there may be a previous jump which jumps to current PC (which is the
67813  * case for iteration and conditional statements, for instance).
67814  */
67815 
67816  /* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
67817  * we could avoid the last RETURN if we could ensure there is no way to get here
67818  * (directly or via a jump)
67819  */
67820 
67821  DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
67822  if (reg_stmt_value >= 0) {
67823  DUK_ASSERT(DUK__ISREG(reg_stmt_value));
67824  duk__emit_bc(comp_ctx, DUK_OP_RETREG, (duk_regconst_t) reg_stmt_value /*reg*/);
67825  } else {
67826  duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
67827  }
67828 
67829  /*
67830  * Peephole optimize JUMP chains.
67831  */
67832 
67833  duk__peephole_optimize_bytecode(comp_ctx);
67834 
67835  /*
67836  * comp_ctx->curr_func is now ready to be converted into an actual
67837  * function template.
67838  */
67839 
67840  DUK__RECURSION_DECREASE(comp_ctx, thr);
67841  return;
67842 
67843  error_funcname:
67844  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
67845 }
67846 
67847 /*
67848  * Parse a function-like expression:
67849  *
67850  * - function expression
67851  * - function declaration
67852  * - function statement (non-standard)
67853  * - setter/getter
67854  *
67855  * Adds the function to comp_ctx->curr_func function table and returns the
67856  * function number.
67857  *
67858  * On entry, curr_token points to:
67859  *
67860  * - the token after 'function' for function expression/declaration/statement
67861  * - the token after 'set' or 'get' for setter/getter
67862  */
67863 
67864 /* Parse formals. */
67865 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
67866  duk_hthread *thr = comp_ctx->thr;
67867  duk_context *ctx = (duk_context *) thr;
67868  duk_bool_t first = 1;
67869  duk_uarridx_t n;
67870 
67871  for (;;) {
67872  if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
67873  break;
67874  }
67875 
67876  if (first) {
67877  /* no comma */
67878  first = 0;
67879  } else {
67880  duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
67881  }
67882 
67883  /* Note: when parsing a formal list in non-strict context, e.g.
67884  * "implements" is parsed as an identifier. When the function is
67885  * later detected to be strict, the argument list must be rechecked
67886  * against a larger set of reserved words (that of strict mode).
67887  * This is handled by duk__parse_func_body(). Here we recognize
67888  * whatever tokens are considered reserved in current strictness
67889  * (which is not always enough).
67890  */
67891 
67892  if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
67893  DUK_ERROR_SYNTAX(thr, "expected identifier");
67894  }
67895  DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
67896  DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
67897  DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
67898  (duk_heaphdr *) comp_ctx->curr_token.str1));
67899 
67900  /* XXX: append primitive */
67901  duk_push_hstring(ctx, comp_ctx->curr_token.str1);
67902  n = (duk_uarridx_t) duk_get_length(ctx, comp_ctx->curr_func.argnames_idx);
67903  duk_put_prop_index(ctx, comp_ctx->curr_func.argnames_idx, n);
67904 
67905  duk__advance(comp_ctx); /* eat identifier */
67906  }
67907 }
67908 
67909 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
67910  * correctly set up. Assumes that curr_token is just after 'function' (or
67911  * 'set'/'get' etc).
67912  */
67913 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
67914  duk_hthread *thr = comp_ctx->thr;
67915  duk_context *ctx = (duk_context *) thr;
67916  duk_token *tok;
67917  duk_bool_t no_advance;
67918 
67919  DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
67920  DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
67921  DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
67922  DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
67923  DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
67924 
67925  duk__update_lineinfo_currtoken(comp_ctx);
67926 
67927  /*
67928  * Function name (if any)
67929  *
67930  * We don't check for prohibited names here, because we don't
67931  * yet know whether the function will be strict. Function body
67932  * parsing handles this retroactively.
67933  *
67934  * For function expressions and declarations function name must
67935  * be an Identifer (excludes reserved words). For setter/getter
67936  * it is a PropertyName which allows reserved words and also
67937  * strings and numbers (e.g. "{ get 1() { ... } }").
67938  *
67939  * Function parsing may start either from prev_token or curr_token
67940  * (object literal method definition uses prev_token for example).
67941  * This is dealt with for the initial token.
67942  */
67943 
67944  no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
67945  if (no_advance) {
67946  tok = &comp_ctx->prev_token;
67947  } else {
67948  tok = &comp_ctx->curr_token;
67949  }
67950 
67951  if (flags & DUK__FUNC_FLAG_GETSET) {
67952  /* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
67953  if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
67954  duk_push_hstring(ctx, tok->str1); /* keep in valstack */
67955  } else if (tok->t == DUK_TOK_NUMBER) {
67956  duk_push_number(ctx, tok->num);
67957  duk_to_string(ctx, -1);
67958  } else {
67959  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
67960  }
67961  comp_ctx->curr_func.h_name = duk_known_hstring(ctx, -1); /* borrowed reference */
67962  } else {
67963  /* Function name is an Identifier (not IdentifierName), but we get
67964  * the raw name (not recognizing keywords) here and perform the name
67965  * checks only after pass 1.
67966  */
67967  if (tok->t_nores == DUK_TOK_IDENTIFIER) {
67968  duk_push_hstring(ctx, tok->str1); /* keep in valstack */
67969  comp_ctx->curr_func.h_name = duk_known_hstring(ctx, -1); /* borrowed reference */
67970  } else {
67971  /* valstack will be unbalanced, which is OK */
67972  DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
67973  DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
67974  no_advance = 1;
67975  if (flags & DUK__FUNC_FLAG_DECL) {
67976  DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
67977  }
67978  }
67979  }
67980 
67981  DUK_DD(DUK_DDPRINT("function name: %!O",
67982  (duk_heaphdr *) comp_ctx->curr_func.h_name));
67983 
67984  if (!no_advance) {
67985  duk__advance(comp_ctx);
67986  }
67987 
67988  /*
67989  * Formal argument list
67990  *
67991  * We don't check for prohibited names or for duplicate argument
67992  * names here, becase we don't yet know whether the function will
67993  * be strict. Function body parsing handles this retroactively.
67994  */
67995 
67996  duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
67997 
67998  duk__parse_func_formals(comp_ctx);
67999 
68000  DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
68001  duk__advance(comp_ctx);
68002 
68003  /*
68004  * Parse function body
68005  */
68006 
68007  duk__parse_func_body(comp_ctx,
68008  0, /* expect_eof */
68009  0, /* implicit_return_value */
68010  DUK_TOK_LCURLY); /* expect_token */
68011 
68012  /*
68013  * Convert duk_compiler_func to a function template and add it
68014  * to the parent function table.
68015  */
68016 
68017  duk__convert_to_func_template(comp_ctx); /* -> [ ... func ] */
68018 }
68019 
68020 /* Parse an inner function, adding the function template to the current function's
68021  * function table. Return a function number to be used by the outer function.
68022  *
68023  * Avoiding O(depth^2) inner function parsing is handled here. On the first pass,
68024  * compile and register the function normally into the 'funcs' array, also recording
68025  * a lexer point (offset/line) to the closing brace of the function. On the second
68026  * pass, skip the function and return the same 'fnum' as on the first pass by using
68027  * a running counter.
68028  *
68029  * An unfortunate side effect of this is that when parsing the inner function, almost
68030  * nothing is known of the outer function, i.e. the inner function's scope. We don't
68031  * need that information at the moment, but it would allow some optimizations if it
68032  * were used.
68033  */
68034 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
68035  duk_hthread *thr = comp_ctx->thr;
68036  duk_context *ctx = (duk_context *) thr;
68037  duk_compiler_func old_func;
68038  duk_idx_t entry_top;
68039  duk_int_t fnum;
68040 
68041  /*
68042  * On second pass, skip the function.
68043  */
68044 
68045  if (!comp_ctx->curr_func.in_scanning) {
68046  duk_lexer_point lex_pt;
68047 
68048  fnum = comp_ctx->curr_func.fnum_next++;
68049  duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
68050  lex_pt.offset = duk_to_int(ctx, -1);
68051  duk_pop(ctx);
68052  duk_get_prop_index(ctx, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
68053  lex_pt.line = duk_to_int(ctx, -1);
68054  duk_pop(ctx);
68055 
68056  DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
68057  (long) lex_pt.offset, (long) lex_pt.line));
68058 
68059  DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
68060  comp_ctx->curr_token.t = 0; /* this is needed for regexp mode */
68061  comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
68062  duk__advance(comp_ctx);
68063  duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
68064 
68065  return fnum;
68066  }
68067 
68068  /*
68069  * On first pass, perform actual parsing. Remember valstack top on entry
68070  * to restore it later, and switch to using a new function in comp_ctx.
68071  */
68072 
68073  entry_top = duk_get_top(ctx);
68074  DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
68075  (long) entry_top, (long) comp_ctx->curr_token.start_offset));
68076 
68077  DUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
68078 
68079  DUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));
68080  duk__init_func_valstack_slots(comp_ctx);
68081  DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
68082 
68083  /* inherit initial strictness from parent */
68084  comp_ctx->curr_func.is_strict = old_func.is_strict;
68085 
68086  /* XXX: It might be better to just store the flags into the curr_func
68087  * struct and use them as is without this flag interpretation step
68088  * here.
68089  */
68090  DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
68091  comp_ctx->curr_func.is_function = 1;
68092  DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
68093  DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
68094  comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
68095  comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
68096  DUK__FUNC_FLAG_METDEF |
68097  DUK__FUNC_FLAG_DECL)); /* no name binding for: declarations, objlit getset, objlit method def */
68098  comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
68099  DUK__FUNC_FLAG_METDEF)); /* not constructable: objlit getset, objlit method def */
68100 
68101  /*
68102  * Parse inner function
68103  */
68104 
68105  duk__parse_func_like_raw(comp_ctx, flags); /* pushes function template */
68106 
68107  /* prev_token.start_offset points to the closing brace here; when skipping
68108  * we're going to reparse the closing brace to ensure semicolon insertion
68109  * etc work as expected.
68110  */
68111  DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
68112  (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
68113  DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
68114 
68115  /* XXX: append primitive */
68116  DUK_ASSERT(duk_get_length(ctx, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
68117  fnum = old_func.fnum_next++;
68118 
68119  if (fnum > DUK__MAX_FUNCS) {
68120  DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
68121  }
68122 
68123  /* array writes autoincrement length */
68124  (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
68125  duk_push_size_t(ctx, comp_ctx->prev_token.start_offset);
68126  (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
68127  duk_push_int(ctx, comp_ctx->prev_token.start_line);
68128  (void) duk_put_prop_index(ctx, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
68129 
68130  /*
68131  * Cleanup: restore original function, restore valstack state.
68132  *
68133  * Function declaration handling needs the function name to be pushed
68134  * on the value stack.
68135  */
68136 
68137  if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
68138  DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
68139  duk_push_hstring(ctx, comp_ctx->curr_func.h_name);
68140  duk_replace(ctx, entry_top);
68141  duk_set_top(ctx, entry_top + 1);
68142  } else {
68143  duk_set_top(ctx, entry_top);
68144  }
68145  DUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
68146 
68147  return fnum;
68148 }
68149 
68150 /*
68151  * Compile input string into an executable function template without
68152  * arguments.
68153  *
68154  * The string is parsed as the "Program" production of Ecmascript E5.
68155  * Compilation context can be either global code or eval code (see E5
68156  * Sections 14 and 15.1.2.1).
68157  *
68158  * Input stack: [ ... filename ]
68159  * Output stack: [ ... func_template ]
68160  */
68161 
68162 /* XXX: source code property */
68163 
68164 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_context *ctx, void *udata) {
68165  duk_hthread *thr = (duk_hthread *) ctx;
68166  duk_hstring *h_filename;
68167  duk__compiler_stkstate *comp_stk;
68168  duk_compiler_ctx *comp_ctx;
68169  duk_lexer_point *lex_pt;
68170  duk_compiler_func *func;
68171  duk_idx_t entry_top;
68172  duk_bool_t is_strict;
68173  duk_bool_t is_eval;
68174  duk_bool_t is_funcexpr;
68175  duk_small_uint_t flags;
68176 
68177  DUK_ASSERT(thr != NULL);
68178  DUK_ASSERT(udata != NULL);
68179 
68180  /*
68181  * Arguments check
68182  */
68183 
68184  entry_top = duk_get_top(ctx);
68185  DUK_ASSERT(entry_top >= 1);
68186 
68187  comp_stk = (duk__compiler_stkstate *) udata;
68188  comp_ctx = &comp_stk->comp_ctx_alloc;
68189  lex_pt = &comp_stk->lex_pt_alloc;
68190  DUK_ASSERT(comp_ctx != NULL);
68191  DUK_ASSERT(lex_pt != NULL);
68192 
68193  flags = comp_stk->flags;
68194  is_eval = (flags & DUK_JS_COMPILE_FLAG_EVAL ? 1 : 0);
68195  is_strict = (flags & DUK_JS_COMPILE_FLAG_STRICT ? 1 : 0);
68196  is_funcexpr = (flags & DUK_JS_COMPILE_FLAG_FUNCEXPR ? 1 : 0);
68197 
68198  h_filename = duk_get_hstring(ctx, -1); /* may be undefined */
68199 
68200  /*
68201  * Init compiler and lexer contexts
68202  */
68203 
68204  func = &comp_ctx->curr_func;
68205 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
68206  comp_ctx->thr = NULL;
68207  comp_ctx->h_filename = NULL;
68208  comp_ctx->prev_token.str1 = NULL;
68209  comp_ctx->prev_token.str2 = NULL;
68210  comp_ctx->curr_token.str1 = NULL;
68211  comp_ctx->curr_token.str2 = NULL;
68212 #endif
68213 
68214  duk_require_stack(ctx, DUK__COMPILE_ENTRY_SLOTS);
68215 
68216  duk_push_dynamic_buffer(ctx, 0); /* entry_top + 0 */
68217  duk_push_undefined(ctx); /* entry_top + 1 */
68218  duk_push_undefined(ctx); /* entry_top + 2 */
68219  duk_push_undefined(ctx); /* entry_top + 3 */
68220  duk_push_undefined(ctx); /* entry_top + 4 */
68221 
68222  comp_ctx->thr = thr;
68223  comp_ctx->h_filename = h_filename;
68224  comp_ctx->tok11_idx = entry_top + 1;
68225  comp_ctx->tok12_idx = entry_top + 2;
68226  comp_ctx->tok21_idx = entry_top + 3;
68227  comp_ctx->tok22_idx = entry_top + 4;
68228  comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
68229 
68230  /* comp_ctx->lex has been pre-initialized by caller: it has been
68231  * zeroed and input/input_length has been set.
68232  */
68233  comp_ctx->lex.thr = thr;
68234  /* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
68235  comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
68236  comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
68237  comp_ctx->lex.buf_idx = entry_top + 0;
68238  comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(ctx, entry_top + 0);
68239  DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
68240  comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
68241 
68242  lex_pt->offset = 0;
68243  lex_pt->line = 1;
68244  DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt); /* fills window */
68245  comp_ctx->curr_token.start_line = 0; /* needed for line number tracking (becomes prev_token.start_line) */
68246 
68247  /*
68248  * Initialize function state for a zero-argument function
68249  */
68250 
68251  duk__init_func_valstack_slots(comp_ctx);
68252  DUK_ASSERT(func->num_formals == 0);
68253 
68254  if (is_funcexpr) {
68255  /* Name will be filled from function expression, not by caller.
68256  * This case is used by Function constructor and duk_compile()
68257  * API with the DUK_COMPILE_FUNCTION option.
68258  */
68259  DUK_ASSERT(func->h_name == NULL);
68260  } else {
68261  duk_push_hstring_stridx(ctx, (is_eval ? DUK_STRIDX_EVAL :
68262  DUK_STRIDX_GLOBAL));
68263  func->h_name = duk_get_hstring(ctx, -1);
68264  }
68265 
68266  /*
68267  * Parse a function body or a function-like expression, depending
68268  * on flags.
68269  */
68270 
68271  DUK_ASSERT(func->is_setget == 0);
68272  func->is_strict = is_strict;
68273  DUK_ASSERT(func->is_notail == 0);
68274 
68275  if (is_funcexpr) {
68276  func->is_function = 1;
68277  DUK_ASSERT(func->is_eval == 0);
68278  DUK_ASSERT(func->is_global == 0);
68279  func->is_namebinding = 1;
68280  func->is_constructable = 1;
68281 
68282  duk__advance(comp_ctx); /* init 'curr_token' */
68283  duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
68284  (void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
68285  } else {
68286  DUK_ASSERT(func->is_function == 0);
68287  func->is_eval = is_eval;
68288  func->is_global = !is_eval;
68289  DUK_ASSERT(func->is_namebinding == 0);
68290  DUK_ASSERT(func->is_constructable == 0);
68291 
68292  duk__parse_func_body(comp_ctx,
68293  1, /* expect_eof */
68294  1, /* implicit_return_value */
68295  -1); /* expect_token */
68296  }
68297 
68298  /*
68299  * Convert duk_compiler_func to a function template
68300  */
68301 
68302  duk__convert_to_func_template(comp_ctx);
68303 
68304  /*
68305  * Wrapping duk_safe_call() will mangle the stack, just return stack top
68306  */
68307 
68308  /* [ ... filename (temps) func ] */
68309 
68310  return 1;
68311 }
68312 
68313 DUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {
68314  duk_context *ctx = (duk_context *) thr;
68315  duk__compiler_stkstate comp_stk;
68316  duk_compiler_ctx *prev_ctx;
68317  duk_ret_t safe_rc;
68318 
68319  DUK_ASSERT(thr != NULL);
68320  DUK_ASSERT(src_buffer != NULL);
68321 
68322  /* preinitialize lexer state partially */
68323  DUK_MEMZERO(&comp_stk, sizeof(comp_stk));
68324  comp_stk.flags = flags;
68325  DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
68326  comp_stk.comp_ctx_alloc.lex.input = src_buffer;
68327  comp_stk.comp_ctx_alloc.lex.input_length = src_length;
68328 
68329  /* [ ... filename ] */
68330 
68331  prev_ctx = thr->compile_ctx;
68332  thr->compile_ctx = &comp_stk.comp_ctx_alloc; /* for duk_error_augment.c */
68333  safe_rc = duk_safe_call(ctx, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nret*/);
68334  thr->compile_ctx = prev_ctx; /* must restore reliably before returning */
68335 
68336  if (safe_rc != DUK_EXEC_SUCCESS) {
68337  DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(ctx, -1)));
68338  (void) duk_throw(ctx);
68339  }
68340 
68341  /* [ ... template ] */
68342 }
68343 
68344 /* automatic undefs */
68345 #undef DUK__ALLOCTEMP
68346 #undef DUK__ALLOCTEMPS
68347 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
68348 #undef DUK__BC_INITIAL_INSTS
68349 #undef DUK__BP_ADDITIVE
68350 #undef DUK__BP_ASSIGNMENT
68351 #undef DUK__BP_BAND
68352 #undef DUK__BP_BOR
68353 #undef DUK__BP_BXOR
68354 #undef DUK__BP_CALL
68355 #undef DUK__BP_CLOSING
68356 #undef DUK__BP_COMMA
68357 #undef DUK__BP_CONDITIONAL
68358 #undef DUK__BP_EOF
68359 #undef DUK__BP_EQUALITY
68360 #undef DUK__BP_EXPONENTIATION
68361 #undef DUK__BP_FOR_EXPR
68362 #undef DUK__BP_INVALID
68363 #undef DUK__BP_LAND
68364 #undef DUK__BP_LOR
68365 #undef DUK__BP_MEMBER
68366 #undef DUK__BP_MULTIPLICATIVE
68367 #undef DUK__BP_POSTFIX
68368 #undef DUK__BP_RELATIONAL
68369 #undef DUK__BP_SHIFT
68370 #undef DUK__COMPILE_ENTRY_SLOTS
68371 #undef DUK__CONST_MARKER
68372 #undef DUK__DUMP_ISPEC
68373 #undef DUK__DUMP_IVALUE
68374 #undef DUK__EMIT_FLAG_A_IS_SOURCE
68375 #undef DUK__EMIT_FLAG_BC_REGCONST
68376 #undef DUK__EMIT_FLAG_B_IS_TARGET
68377 #undef DUK__EMIT_FLAG_C_IS_TARGET
68378 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
68379 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
68380 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
68381 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
68382 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
68383 #undef DUK__EXPR_FLAG_REJECT_IN
68384 #undef DUK__EXPR_FLAG_REQUIRE_INIT
68385 #undef DUK__EXPR_RBP_MASK
68386 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
68387 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
68388 #undef DUK__FUNC_FLAG_DECL
68389 #undef DUK__FUNC_FLAG_GETSET
68390 #undef DUK__FUNC_FLAG_METDEF
68391 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
68392 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
68393 #undef DUK__GETCONST_MAX_CONSTS_CHECK
68394 #undef DUK__GETTEMP
68395 #undef DUK__HAS_TERM
68396 #undef DUK__HAS_VAL
68397 #undef DUK__ISCONST
68398 #undef DUK__ISREG
68399 #undef DUK__ISTEMP
68400 #undef DUK__IS_TERMINAL
68401 #undef DUK__IVAL_FLAG_ALLOW_CONST
68402 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
68403 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
68404 #undef DUK__MAX_ARRAY_INIT_VALUES
68405 #undef DUK__MAX_CONSTS
68406 #undef DUK__MAX_FUNCS
68407 #undef DUK__MAX_OBJECT_INIT_PAIRS
68408 #undef DUK__MAX_TEMPS
68409 #undef DUK__MK_LBP
68410 #undef DUK__MK_LBP_FLAGS
68411 #undef DUK__OBJ_LIT_KEY_GET
68412 #undef DUK__OBJ_LIT_KEY_PLAIN
68413 #undef DUK__OBJ_LIT_KEY_SET
68414 #undef DUK__PARSE_EXPR_SLOTS
68415 #undef DUK__PARSE_STATEMENTS_SLOTS
68416 #undef DUK__RECURSION_DECREASE
68417 #undef DUK__RECURSION_INCREASE
68418 #undef DUK__REMOVECONST
68419 #undef DUK__SETTEMP
68420 #undef DUK__SETTEMP_CHECKMAX
68421 #undef DUK__STILL_PROLOGUE
68422 #undef DUK__TOKEN_LBP_BP_MASK
68423 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
68424 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
68425 #undef DUK__TOKEN_LBP_FLAG_UNUSED
68426 #undef DUK__TOKEN_LBP_GET_BP
68427 /*
68428  * Ecmascript bytecode executor.
68429  */
68430 
68431 /* #include duk_internal.h -> already included */
68432 
68433 /*
68434  * Local declarations.
68435  */
68436 
68437 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top);
68438 
68439 /*
68440  * Misc helpers.
68441  */
68442 
68443 /* Forced inline declaration, only applied for performance oriented build. */
68444 #if defined(DUK_USE_EXEC_PREFER_SIZE)
68445 #define DUK__INLINE_PERF
68446 #else
68447 #define DUK__INLINE_PERF DUK_ALWAYS_INLINE
68448 #endif
68449 
68450 /* Replace value stack top to value at 'tv_ptr'. Optimize for
68451  * performance by only applying the net refcount change.
68452  */
68453 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
68454  duk_hthread *duk__thr; \
68455  duk_tval *duk__tvsrc; \
68456  duk_tval *duk__tvdst; \
68457  duk_tval duk__tvtmp; \
68458  duk__thr = (thr); \
68459  duk__tvsrc = DUK_GET_TVAL_NEGIDX((duk_context *) duk__thr, -1); \
68460  duk__tvdst = (tv_ptr); \
68461  DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
68462  DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
68463  DUK_TVAL_SET_UNDEFINED(duk__tvsrc); /* value stack init policy */ \
68464  duk__thr->valstack_top = duk__tvsrc; \
68465  DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
68466  } while (0)
68467 
68468 /* XXX: candidate of being an internal shared API call */
68469 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
68470 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
68471  duk_tval *tv_dst;
68472  duk_size_t copy_size;
68473  duk_size_t i;
68474 
68475  tv_dst = thr->valstack_top;
68476  copy_size = sizeof(duk_tval) * count;
68477  DUK_MEMCPY((void *) tv_dst, (const void *) tv_src, copy_size);
68478  for (i = 0; i < count; i++) {
68479  DUK_TVAL_INCREF(thr, tv_dst);
68480  tv_dst++;
68481  }
68482  thr->valstack_top = tv_dst;
68483 }
68484 #endif
68485 
68486 /*
68487  * Arithmetic, binary, and logical helpers.
68488  *
68489  * Note: there is no opcode for logical AND or logical OR; this is on
68490  * purpose, because the evalution order semantics for them make such
68491  * opcodes pretty pointless: short circuiting means they are most
68492  * comfortably implemented as jumps. However, a logical NOT opcode
68493  * is useful.
68494  *
68495  * Note: careful with duk_tval pointers here: they are potentially
68496  * invalidated by any DECREF and almost any API call. It's still
68497  * preferable to work without making a copy but that's not always
68498  * possible.
68499  */
68500 
68501 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
68502  return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
68503 }
68504 
68505 #if defined(DUK_USE_ES7_EXP_OPERATOR)
68506 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
68507  return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
68508 }
68509 #endif
68510 
68511 DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {
68512  /*
68513  * Addition operator is different from other arithmetic
68514  * operations in that it also provides string concatenation.
68515  * Hence it is implemented separately.
68516  *
68517  * There is a fast path for number addition. Other cases go
68518  * through potentially multiple coercions as described in the
68519  * E5 specification. It may be possible to reduce the number
68520  * of coercions, but this must be done carefully to preserve
68521  * the exact semantics.
68522  *
68523  * E5 Section 11.6.1.
68524  *
68525  * Custom types also have special behavior implemented here.
68526  */
68527 
68528  duk_context *ctx = (duk_context *) thr;
68529  duk_double_union du;
68530 
68531  DUK_ASSERT(thr != NULL);
68532  DUK_ASSERT(ctx != NULL);
68533  DUK_ASSERT(tv_x != NULL); /* may be reg or const */
68534  DUK_ASSERT(tv_y != NULL); /* may be reg or const */
68535  DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
68536  DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
68537 
68538  /*
68539  * Fast paths
68540  */
68541 
68542 #if defined(DUK_USE_FASTINT)
68543  if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
68544  duk_int64_t v1, v2, v3;
68545  duk_int32_t v3_hi;
68546  duk_tval *tv_z;
68547 
68548  /* Input values are signed 48-bit so we can detect overflow
68549  * reliably from high bits or just a comparison.
68550  */
68551 
68552  v1 = DUK_TVAL_GET_FASTINT(tv_x);
68553  v2 = DUK_TVAL_GET_FASTINT(tv_y);
68554  v3 = v1 + v2;
68555  v3_hi = (duk_int32_t) (v3 >> 32);
68556  if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
68557  tv_z = thr->valstack_bottom + idx_z;
68558  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
68559  return;
68560  } else {
68561  /* overflow, fall through */
68562  ;
68563  }
68564  }
68565 #endif /* DUK_USE_FASTINT */
68566 
68567  if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
68568 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
68569  duk_tval *tv_z;
68570 #endif
68571 
68572  du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
68573 #if defined(DUK_USE_EXEC_PREFER_SIZE)
68574  duk_push_number(ctx, du.d); /* will NaN normalize result */
68575  duk_replace(ctx, idx_z);
68576 #else /* DUK_USE_EXEC_PREFER_SIZE */
68577  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
68578  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
68579  tv_z = thr->valstack_bottom + idx_z;
68580  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
68581 #endif /* DUK_USE_EXEC_PREFER_SIZE */
68582  return;
68583  }
68584 
68585  /*
68586  * Slow path: potentially requires function calls for coercion
68587  */
68588 
68589  duk_push_tval(ctx, tv_x);
68590  duk_push_tval(ctx, tv_y);
68591  duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* side effects -> don't use tv_x, tv_y after */
68592  duk_to_primitive(ctx, -1, DUK_HINT_NONE);
68593 
68594  /* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
68595  if (duk_is_string(ctx, -2) || duk_is_string(ctx, -1)) {
68596  /* Symbols shouldn't technically be handled here, but should
68597  * go into the default ToNumber() coercion path instead and
68598  * fail there with a TypeError. However, there's a ToString()
68599  * here which also fails with TypeError so no explicit check
68600  * is needed.
68601  */
68602  duk_to_string(ctx, -2);
68603  duk_to_string(ctx, -1);
68604  duk_concat(ctx, 2); /* [... s1 s2] -> [... s1+s2] */
68605  } else {
68606  duk_double_t d1, d2;
68607 
68608  d1 = duk_to_number_m2(ctx);
68609  d2 = duk_to_number_m1(ctx);
68610  DUK_ASSERT(duk_is_number(ctx, -2));
68611  DUK_ASSERT(duk_is_number(ctx, -1));
68612  DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
68613  DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
68614 
68615  du.d = d1 + d2;
68616  duk_pop_2(ctx);
68617  duk_push_number(ctx, du.d); /* will NaN normalize result */
68618  }
68619  duk_replace(ctx, (duk_idx_t) idx_z); /* side effects */
68620 }
68621 
68622 DUK_LOCAL DUK__INLINE_PERF 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) {
68623  /*
68624  * Arithmetic operations other than '+' have number-only semantics
68625  * and are implemented here. The separate switch-case here means a
68626  * "double dispatch" of the arithmetic opcode, but saves code space.
68627  *
68628  * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
68629  */
68630 
68631  duk_context *ctx = (duk_context *) thr;
68632  duk_double_t d1, d2;
68633  duk_double_union du;
68634  duk_small_uint_fast_t opcode_shifted;
68635 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
68636  duk_tval *tv_z;
68637 #endif
68638 
68639  DUK_ASSERT(thr != NULL);
68640  DUK_ASSERT(ctx != NULL);
68641  DUK_ASSERT(tv_x != NULL); /* may be reg or const */
68642  DUK_ASSERT(tv_y != NULL); /* may be reg or const */
68643  DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
68644  DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
68645 
68646  opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
68647 
68648 #if defined(DUK_USE_FASTINT)
68649  if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
68650  duk_int64_t v1, v2, v3;
68651  duk_int32_t v3_hi;
68652 
68653  v1 = DUK_TVAL_GET_FASTINT(tv_x);
68654  v2 = DUK_TVAL_GET_FASTINT(tv_y);
68655 
68656  switch (opcode_shifted) {
68657  case DUK_OP_SUB >> 2: {
68658  v3 = v1 - v2;
68659  break;
68660  }
68661  case DUK_OP_MUL >> 2: {
68662  /* Must ensure result is 64-bit (no overflow); a
68663  * simple and sufficient fast path is to allow only
68664  * 32-bit inputs. Avoid zero inputs to avoid
68665  * negative zero issues (-1 * 0 = -0, for instance).
68666  */
68667  if (v1 >= -0x80000000LL && v1 <= 0x7fffffffLL && v1 != 0 &&
68668  v2 >= -0x80000000LL && v2 <= 0x7fffffffLL && v2 != 0) {
68669  v3 = v1 * v2;
68670  } else {
68671  goto skip_fastint;
68672  }
68673  break;
68674  }
68675  case DUK_OP_DIV >> 2: {
68676  /* Don't allow a zero divisor. Fast path check by
68677  * "verifying" with multiplication. Also avoid zero
68678  * dividend to avoid negative zero issues (0 / -1 = -0
68679  * for instance).
68680  */
68681  if (v1 == 0 || v2 == 0) {
68682  goto skip_fastint;
68683  }
68684  v3 = v1 / v2;
68685  if (v3 * v2 != v1) {
68686  goto skip_fastint;
68687  }
68688  break;
68689  }
68690  case DUK_OP_MOD >> 2: {
68691  /* Don't allow a zero divisor. Restrict both v1 and
68692  * v2 to positive values to avoid compiler specific
68693  * behavior.
68694  */
68695  if (v1 < 1 || v2 < 1) {
68696  goto skip_fastint;
68697  }
68698  v3 = v1 % v2;
68699  DUK_ASSERT(v3 >= 0);
68700  DUK_ASSERT(v3 < v2);
68701  DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
68702  break;
68703  }
68704  default: {
68705  DUK_UNREACHABLE();
68706  goto skip_fastint;
68707  }
68708  }
68709 
68710  v3_hi = (duk_int32_t) (v3 >> 32);
68711  if (DUK_LIKELY(v3_hi >= -0x8000LL && v3_hi <= 0x7fffLL)) {
68712  tv_z = thr->valstack_bottom + idx_z;
68713  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3); /* side effects */
68714  return;
68715  }
68716  /* fall through if overflow etc */
68717  }
68718  skip_fastint:
68719 #endif /* DUK_USE_FASTINT */
68720 
68721  if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
68722  /* fast path */
68723  d1 = DUK_TVAL_GET_NUMBER(tv_x);
68724  d2 = DUK_TVAL_GET_NUMBER(tv_y);
68725  } else {
68726  duk_push_tval(ctx, tv_x);
68727  duk_push_tval(ctx, tv_y);
68728  d1 = duk_to_number_m2(ctx); /* side effects */
68729  d2 = duk_to_number_m1(ctx);
68730  DUK_ASSERT(duk_is_number(ctx, -2));
68731  DUK_ASSERT(duk_is_number(ctx, -1));
68732  DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
68733  DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
68734  duk_pop_2(ctx);
68735  }
68736 
68737  switch (opcode_shifted) {
68738  case DUK_OP_SUB >> 2: {
68739  du.d = d1 - d2;
68740  break;
68741  }
68742  case DUK_OP_MUL >> 2: {
68743  du.d = d1 * d2;
68744  break;
68745  }
68746  case DUK_OP_DIV >> 2: {
68747  du.d = d1 / d2;
68748  break;
68749  }
68750  case DUK_OP_MOD >> 2: {
68751  du.d = duk__compute_mod(d1, d2);
68752  break;
68753  }
68754 #if defined(DUK_USE_ES7_EXP_OPERATOR)
68755  case DUK_OP_EXP >> 2: {
68756  du.d = duk__compute_exp(d1, d2);
68757  break;
68758  }
68759 #endif
68760  default: {
68761  DUK_UNREACHABLE();
68762  du.d = DUK_DOUBLE_NAN; /* should not happen */
68763  break;
68764  }
68765  }
68766 
68767 #if defined(DUK_USE_EXEC_PREFER_SIZE)
68768  duk_push_number(ctx, du.d); /* will NaN normalize result */
68769  duk_replace(ctx, idx_z);
68770 #else /* DUK_USE_EXEC_PREFER_SIZE */
68771  /* important to use normalized NaN with 8-byte tagged types */
68772  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
68773  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
68774  tv_z = thr->valstack_bottom + idx_z;
68775  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d); /* side effects */
68776 #endif /* DUK_USE_EXEC_PREFER_SIZE */
68777 }
68778 
68779 DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {
68780  /*
68781  * Binary bitwise operations use different coercions (ToInt32, ToUint32)
68782  * depending on the operation. We coerce the arguments first using
68783  * ToInt32(), and then cast to an 32-bit value if necessary. Note that
68784  * such casts must be correct even if there is no native 32-bit type
68785  * (e.g., duk_int32_t and duk_uint32_t are 64-bit).
68786  *
68787  * E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
68788  */
68789 
68790  duk_context *ctx = (duk_context *) thr;
68791  duk_int32_t i1, i2, i3;
68792  duk_uint32_t u1, u2, u3;
68793 #if defined(DUK_USE_FASTINT)
68794  duk_int64_t fi3;
68795 #else
68796  duk_double_t d3;
68797 #endif
68798  duk_small_uint_fast_t opcode_shifted;
68799 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
68800  duk_tval *tv_z;
68801 #endif
68802 
68803  DUK_ASSERT(thr != NULL);
68804  DUK_ASSERT(ctx != NULL);
68805  DUK_ASSERT(tv_x != NULL); /* may be reg or const */
68806  DUK_ASSERT(tv_y != NULL); /* may be reg or const */
68807  DUK_ASSERT_DISABLE(idx_z >= 0); /* unsigned */
68808  DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(ctx));
68809 
68810  opcode_shifted = opcode >> 2; /* Get base opcode without reg/const modifiers. */
68811 
68812 #if defined(DUK_USE_FASTINT)
68813  if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
68814  i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
68815  i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
68816  }
68817  else
68818 #endif /* DUK_USE_FASTINT */
68819  {
68820  duk_push_tval(ctx, tv_x);
68821  duk_push_tval(ctx, tv_y);
68822  i1 = duk_to_int32(ctx, -2);
68823  i2 = duk_to_int32(ctx, -1);
68824  duk_pop_2(ctx);
68825  }
68826 
68827  switch (opcode_shifted) {
68828  case DUK_OP_BAND >> 2: {
68829  i3 = i1 & i2;
68830  break;
68831  }
68832  case DUK_OP_BOR >> 2: {
68833  i3 = i1 | i2;
68834  break;
68835  }
68836  case DUK_OP_BXOR >> 2: {
68837  i3 = i1 ^ i2;
68838  break;
68839  }
68840  case DUK_OP_BASL >> 2: {
68841  /* Signed shift, named "arithmetic" (asl) because the result
68842  * is signed, e.g. 4294967295 << 1 -> -2. Note that result
68843  * must be masked.
68844  */
68845 
68846  u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
68847  i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL)); /* E5 Section 11.7.1, steps 7 and 8 */
68848  i3 = i3 & ((duk_int32_t) 0xffffffffUL); /* Note: left shift, should mask */
68849  break;
68850  }
68851  case DUK_OP_BASR >> 2: {
68852  /* signed shift */
68853 
68854  u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
68855  i3 = i1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
68856  break;
68857  }
68858  case DUK_OP_BLSR >> 2: {
68859  /* unsigned shift */
68860 
68861  u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
68862  u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
68863 
68864  /* special result value handling */
68865  u3 = u1 >> (u2 & 0x1fUL); /* E5 Section 11.7.2, steps 7 and 8 */
68866 #if defined(DUK_USE_FASTINT)
68867  fi3 = (duk_int64_t) u3;
68868  goto fastint_result_set;
68869 #else
68870  d3 = (duk_double_t) u3;
68871  goto result_set;
68872 #endif
68873  }
68874  default: {
68875  DUK_UNREACHABLE();
68876  i3 = 0; /* should not happen */
68877  break;
68878  }
68879  }
68880 
68881 #if defined(DUK_USE_FASTINT)
68882  /* Result is always fastint compatible. */
68883  /* XXX: Set 32-bit result (but must then handle signed and
68884  * unsigned results separately).
68885  */
68886  fi3 = (duk_int64_t) i3;
68887 
68888  fastint_result_set:
68889  tv_z = thr->valstack_bottom + idx_z;
68890  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3); /* side effects */
68891 #else /* DUK_USE_FASTINT */
68892  d3 = (duk_double_t) i3;
68893 
68894  result_set:
68895  DUK_ASSERT(!DUK_ISNAN(d3)); /* 'd3' is never NaN, so no need to normalize */
68896  DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3); /* always normalized */
68897 
68898 #if defined(DUK_USE_EXEC_PREFER_SIZE)
68899  duk_push_number(ctx, d3); /* would NaN normalize result, but unnecessary */
68900  duk_replace(ctx, idx_z);
68901 #else /* DUK_USE_EXEC_PREFER_SIZE */
68902  tv_z = thr->valstack_bottom + idx_z;
68903  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3); /* side effects */
68904 #endif /* DUK_USE_EXEC_PREFER_SIZE */
68905 #endif /* DUK_USE_FASTINT */
68906 }
68907 
68908 /* In-place unary operation. */
68909 DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_idx_t idx_src, duk_idx_t idx_dst, duk_small_uint_fast_t opcode) {
68910  /*
68911  * Arithmetic operations other than '+' have number-only semantics
68912  * and are implemented here. The separate switch-case here means a
68913  * "double dispatch" of the arithmetic opcode, but saves code space.
68914  *
68915  * E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
68916  */
68917 
68918  duk_context *ctx = (duk_context *) thr;
68919  duk_tval *tv;
68920  duk_double_t d1;
68921  duk_double_union du;
68922 
68923  DUK_ASSERT(thr != NULL);
68924  DUK_ASSERT(ctx != NULL);
68925  DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
68926  DUK_ASSERT(idx_src >= 0);
68927  DUK_ASSERT(idx_dst >= 0);
68928 
68929  tv = DUK_GET_TVAL_POSIDX(ctx, idx_src);
68930 
68931 #if defined(DUK_USE_FASTINT)
68932  if (DUK_TVAL_IS_FASTINT(tv)) {
68933  duk_int64_t v1, v2;
68934 
68935  v1 = DUK_TVAL_GET_FASTINT(tv);
68936  if (opcode == DUK_OP_UNM) {
68937  /* The smallest fastint is no longer 48-bit when
68938  * negated. Positive zero becames negative zero
68939  * (cannot be represented) when negated.
68940  */
68941  if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
68942  v2 = -v1;
68943  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
68944  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
68945  return;
68946  }
68947  } else {
68948  /* ToNumber() for a fastint is a no-op. */
68949  DUK_ASSERT(opcode == DUK_OP_UNP);
68950  v2 = v1;
68951  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
68952  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
68953  return;
68954  }
68955  /* fall through if overflow etc */
68956  }
68957 #endif /* DUK_USE_FASTINT */
68958 
68959  if (DUK_TVAL_IS_NUMBER(tv)) {
68960  d1 = DUK_TVAL_GET_NUMBER(tv);
68961  } else {
68962  d1 = duk_to_number(ctx, idx_src); /* side effects, perform in-place */
68963  DUK_ASSERT(DUK_TVAL_IS_NUMBER(DUK_GET_TVAL_POSIDX(ctx, idx_src)));
68964  }
68965 
68966  if (opcode == DUK_OP_UNP) {
68967  /* ToNumber() for a double is a no-op, but unary plus is
68968  * used to force a fastint check so do that here.
68969  */
68970  du.d = d1;
68971  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
68972 #if defined(DUK_USE_FASTINT)
68973  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
68974  DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d); /* always 'fast', i.e. inlined */
68975  return;
68976 #endif
68977  } else {
68978  DUK_ASSERT(opcode == DUK_OP_UNM);
68979  du.d = -d1;
68980  DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du); /* mandatory if du.d is a NaN */
68981  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
68982  }
68983 
68984  /* XXX: size optimize: push+replace? */
68985  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
68986  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
68987 }
68988 
68989 DUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {
68990  /*
68991  * E5 Section 11.4.8
68992  */
68993 
68994  duk_context *ctx = (duk_context *) thr;
68995  duk_tval *tv;
68996  duk_int32_t i1, i2;
68997 
68998  DUK_ASSERT(thr != NULL);
68999  DUK_ASSERT(ctx != NULL);
69000  DUK_ASSERT_DISABLE(idx_src >= 0);
69001  DUK_ASSERT_DISABLE(idx_dst >= 0);
69002  DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(ctx));
69003  DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(ctx));
69004  DUK_UNREF(thr); /* w/o refcounts */
69005 
69006  tv = DUK_GET_TVAL_POSIDX(ctx, idx_src);
69007 
69008 #if defined(DUK_USE_FASTINT)
69009  if (DUK_TVAL_IS_FASTINT(tv)) {
69010  i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
69011  }
69012  else
69013 #endif /* DUK_USE_FASTINT */
69014  {
69015  i1 = duk_to_int32(ctx, idx_src); /* side effects */
69016  }
69017 
69018  /* Result is always fastint compatible. */
69019  i2 = ~i1;
69020  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
69021  DUK_TVAL_SET_I32_UPDREF(thr, tv, i2); /* side effects */
69022 }
69023 
69024 DUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_idx_t idx_src, duk_idx_t idx_dst) {
69025  /*
69026  * E5 Section 11.4.9
69027  */
69028 
69029  duk_context *ctx = (duk_context *) thr;
69030  duk_tval *tv;
69031  duk_bool_t res;
69032 
69033  DUK_ASSERT(thr != NULL);
69034  DUK_ASSERT(ctx != NULL);
69035  DUK_ASSERT_DISABLE(idx_src >= 0);
69036  DUK_ASSERT_DISABLE(idx_dst >= 0);
69037  DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(ctx));
69038  DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(ctx));
69039  DUK_UNREF(thr); /* w/o refcounts */
69040 
69041  /* ToBoolean() does not require any operations with side effects so
69042  * we can do it efficiently. For footprint it would be better to use
69043  * duk_js_toboolean() and then push+replace to the result slot.
69044  */
69045  tv = DUK_GET_TVAL_POSIDX(ctx, idx_src);
69046  res = duk_js_toboolean(tv); /* does not modify 'tv' */
69047  DUK_ASSERT(res == 0 || res == 1);
69048  res ^= 1;
69049  tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
69050  /* XXX: size optimize: push+replace? */
69051  DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res); /* side effects */
69052 }
69053 
69054 /* XXX: size optimized variant */
69055 DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {
69056  duk_context *ctx = (duk_context *) thr;
69057  duk_double_t x, y, z;
69058 
69059  /* Two lowest bits of opcode are used to distinguish
69060  * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69061  */
69062  DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
69063  DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
69064  DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
69065  DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
69066 
69067 #if defined(DUK_USE_FASTINT)
69068  if (DUK_TVAL_IS_FASTINT(tv_src)) {
69069  duk_int64_t x_fi, y_fi, z_fi;
69070  x_fi = DUK_TVAL_GET_FASTINT(tv_src);
69071  if (op & 0x01) {
69072  if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
69073  goto skip_fastint;
69074  }
69075  y_fi = x_fi - 1;
69076  } else {
69077  if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
69078  goto skip_fastint;
69079  }
69080  y_fi = x_fi + 1;
69081  }
69082 
69083  DUK_TVAL_SET_FASTINT(tv_src, y_fi); /* no need for refcount update */
69084 
69085  z_fi = (op & 0x02) ? x_fi : y_fi;
69086  DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi); /* side effects */
69087  return;
69088  }
69089  skip_fastint:
69090 #endif
69091  if (DUK_TVAL_IS_NUMBER(tv_src)) {
69092  /* Fast path for the case where the register
69093  * is a number (e.g. loop counter).
69094  */
69095 
69096  x = DUK_TVAL_GET_NUMBER(tv_src);
69097  if (op & 0x01) {
69098  y = x - 1.0;
69099  } else {
69100  y = x + 1.0;
69101  }
69102 
69103  DUK_TVAL_SET_NUMBER(tv_src, y); /* no need for refcount update */
69104  } else {
69105  /* Preserve duk_tval pointer(s) across a potential valstack
69106  * resize by converting them into offsets temporarily.
69107  */
69108  duk_idx_t bc;
69109  duk_size_t off_dst;
69110 
69111  off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
69112  bc = (duk_idx_t) (tv_src - thr->valstack_bottom); /* XXX: pass index explicitly? */
69113  tv_src = NULL; /* no longer referenced */
69114 
69115  x = duk_to_number(ctx, bc);
69116  if (op & 0x01) {
69117  y = x - 1.0;
69118  } else {
69119  y = x + 1.0;
69120  }
69121 
69122  duk_push_number(ctx, y);
69123  duk_replace(ctx, bc);
69124 
69125  tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
69126  }
69127 
69128  z = (op & 0x02) ? x : y;
69129  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z); /* side effects */
69130 }
69131 
69132 DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_uint_t is_strict) {
69133  duk_context *ctx = (duk_context *) thr;
69134  duk_activation *act;
69135  duk_double_t x, y;
69136  duk_hstring *name;
69137 
69138  /* XXX: The pre/post inc/dec for an identifier lookup is
69139  * missing the important fast path where the identifier
69140  * has a storage location e.g. in a scope object so that
69141  * it can be updated in-place. In particular, the case
69142  * where the identifier has a storage location AND the
69143  * previous value is a number should be optimized because
69144  * it's side effect free.
69145  */
69146 
69147  /* Two lowest bits of opcode are used to distinguish
69148  * variants. Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
69149  */
69150  DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
69151  DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
69152  DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
69153  DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
69154 
69155  DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
69156  name = DUK_TVAL_GET_STRING(tv_id);
69157  DUK_ASSERT(name != NULL);
69158  act = thr->callstack + thr->callstack_top - 1;
69159  (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [ ... val this ] */
69160 
69161  /* XXX: Fastint fast path would be useful here. Also fastints
69162  * now lose their fastint status in current handling which is
69163  * not intuitive.
69164  */
69165 
69166  x = duk_to_number_m2(ctx);
69167  if (op & 0x01) {
69168  y = x - 1.0;
69169  } else {
69170  y = x + 1.0;
69171  }
69172 
69173  /* [... x this] */
69174 
69175  if (op & 0x02) {
69176  duk_push_number(ctx, y); /* -> [ ... x this y ] */
69177  duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
69178  duk_pop_2(ctx); /* -> [ ... x ] */
69179  } else {
69180  duk_pop_2(ctx); /* -> [ ... ] */
69181  duk_push_number(ctx, y); /* -> [ ... y ] */
69182  duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
69183  }
69184 
69185 #if defined(DUK_USE_EXEC_PREFER_SIZE)
69186  duk_replace(ctx, (duk_idx_t) idx_dst);
69187 #else /* DUK_USE_EXEC_PREFER_SIZE */
69188  DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(ctx, idx_dst));
69189 #endif /* DUK_USE_EXEC_PREFER_SIZE */
69190 }
69191 
69192 /*
69193  * Longjmp and other control flow transfer for the bytecode executor.
69194  *
69195  * The longjmp handler can handle all longjmp types: error, yield, and
69196  * resume (pseudotypes are never actually thrown).
69197  *
69198  * Error policy for longjmp: should not ordinarily throw errors; if errors
69199  * occur (e.g. due to out-of-memory) they bubble outwards rather than being
69200  * handled recursively.
69201  */
69202 
69203 #define DUK__LONGJMP_RESTART 0 /* state updated, restart bytecode execution */
69204 #define DUK__LONGJMP_RETHROW 1 /* exit bytecode executor by rethrowing an error to caller */
69205 
69206 #define DUK__RETHAND_RESTART 0 /* state updated, restart bytecode execution */
69207 #define DUK__RETHAND_FINISHED 1 /* exit bytecode execution with return value */
69208 
69209 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
69210  * top are combined into one pass.
69211  */
69212 
69213 /* Reconfigure value stack for return to an Ecmascript function at 'act_idx'. */
69214 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr, duk_size_t act_idx) {
69215  duk_activation *act;
69216  duk_hcompfunc *h_func;
69217  duk_idx_t clamp_top;
69218 
69219  DUK_ASSERT(thr != NULL);
69220  DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
69221  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
69222  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
69223  DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
69224 
69225  /* Clamp so that values at 'clamp_top' and above are wiped and won't
69226  * retain reachable garbage. Then extend to 'nregs' because we're
69227  * returning to an Ecmascript function.
69228  */
69229 
69230  act = thr->callstack + act_idx;
69231  h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
69232 
69233  thr->valstack_bottom = thr->valstack + act->idx_bottom;
69234  DUK_ASSERT(act->idx_retval >= act->idx_bottom);
69235  clamp_top = (duk_idx_t) (act->idx_retval - act->idx_bottom + 1); /* +1 = one retval */
69236  duk_set_top((duk_context *) thr, clamp_top);
69237  act = NULL;
69238 
69239  (void) duk_valstack_resize_raw((duk_context *) thr,
69240  (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
69241  h_func->nregs + /* reg count */
69242  DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
69243  DUK_VSRESIZE_FLAG_SHRINK | /* flags */
69244  0 /* no compact */ |
69245  DUK_VSRESIZE_FLAG_THROW);
69246 
69247  duk_set_top((duk_context *) thr, h_func->nregs);
69248 }
69249 
69250 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_size_t act_idx, duk_size_t cat_idx) {
69251  duk_activation *act;
69252  duk_catcher *cat;
69253  duk_hcompfunc *h_func;
69254  duk_idx_t clamp_top;
69255 
69256  DUK_ASSERT(thr != NULL);
69257  DUK_ASSERT_DISABLE(act_idx >= 0); /* unsigned */
69258  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + act_idx) != NULL);
69259  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + act_idx)));
69260  DUK_ASSERT_DISABLE(thr->callstack[act_idx].idx_retval >= 0); /* unsigned */
69261 
69262  act = thr->callstack + act_idx;
69263  cat = thr->catchstack + cat_idx;
69264  h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
69265 
69266  thr->valstack_bottom = thr->valstack + act->idx_bottom;
69267  DUK_ASSERT(cat->idx_base >= act->idx_bottom);
69268  clamp_top = (duk_idx_t) (cat->idx_base - act->idx_bottom + 2); /* +2 = catcher value, catcher lj_type */
69269  duk_set_top((duk_context *) thr, clamp_top);
69270  act = NULL;
69271  cat = NULL;
69272 
69273  (void) duk_valstack_resize_raw((duk_context *) thr,
69274  (thr->valstack_bottom - thr->valstack) + /* bottom of current func */
69275  h_func->nregs + /* reg count */
69276  DUK_VALSTACK_INTERNAL_EXTRA, /* + spare */
69277  DUK_VSRESIZE_FLAG_SHRINK | /* flags */
69278  0 /* no compact */ |
69279  DUK_VSRESIZE_FLAG_THROW);
69280 
69281  duk_set_top((duk_context *) thr, h_func->nregs);
69282 }
69283 
69284 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type. */
69285 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) {
69286  duk_tval *tv1;
69287 
69288  DUK_ASSERT(thr != NULL);
69289  DUK_ASSERT(tv_val_unstable != NULL);
69290 
69291  tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base;
69292  DUK_ASSERT(tv1 < thr->valstack_top);
69293  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
69294 
69295  tv1 = thr->valstack + thr->catchstack[cat_idx].idx_base + 1;
69296  DUK_ASSERT(tv1 < thr->valstack_top);
69297 
69298  DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) lj_type); /* side effects */
69299 }
69300 
69301 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) {
69302  duk_context *ctx;
69303  duk_activation *act;
69304 
69305  DUK_ASSERT(thr != NULL);
69306  DUK_ASSERT(tv_val_unstable != NULL);
69307  ctx = (duk_context *) thr;
69308 
69309  duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
69310 
69311  duk_hthread_catchstack_unwind(thr, cat_idx + 1);
69312  duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
69313 
69314  DUK_ASSERT(thr->callstack_top >= 1);
69315  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
69316  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
69317 
69318  duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
69319 
69320  DUK_ASSERT(thr->callstack_top >= 1);
69321  act = thr->callstack + thr->callstack_top - 1;
69322  act->curr_pc = thr->catchstack[cat_idx].pc_base + 0; /* +0 = catch */
69323  act = NULL;
69324 
69325  /*
69326  * If entering a 'catch' block which requires an automatic
69327  * catch variable binding, create the lexical environment.
69328  *
69329  * The binding is mutable (= writable) but not deletable.
69330  * Step 4 for the catch production in E5 Section 12.14;
69331  * no value is given for CreateMutableBinding 'D' argument,
69332  * which implies the binding is not deletable.
69333  */
69334 
69335  if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(&thr->catchstack[cat_idx])) {
69336  duk_hobject *new_env;
69337  duk_hobject *act_lex_env;
69338 
69339  DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
69340 
69341  /* Note: 'act' is dangerous here because it may get invalidate at many
69342  * points, so we re-lookup it multiple times.
69343  */
69344  DUK_ASSERT(thr->callstack_top >= 1);
69345  act = thr->callstack + thr->callstack_top - 1;
69346 
69347  if (act->lex_env == NULL) {
69348  DUK_ASSERT(act->var_env == NULL);
69349  DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
69350 
69351  /* this may have side effects, so re-lookup act */
69352  duk_js_init_activation_environment_records_delayed(thr, act);
69353  act = thr->callstack + thr->callstack_top - 1;
69354  }
69355  DUK_ASSERT(act->lex_env != NULL);
69356  DUK_ASSERT(act->var_env != NULL);
69357  DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
69358  DUK_UNREF(act); /* unreferenced without assertions */
69359 
69360  act = thr->callstack + thr->callstack_top - 1;
69361  act_lex_env = act->lex_env;
69362  act = NULL; /* invalidated */
69363 
69364  new_env = duk_push_object_helper_proto(ctx,
69365  DUK_HOBJECT_FLAG_EXTENSIBLE |
69366  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
69367  act_lex_env);
69368  DUK_ASSERT(new_env != NULL);
69369  DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
69370 
69371  /* Note: currently the catch binding is handled without a register
69372  * binding because we don't support dynamic register bindings (they
69373  * must be fixed for an entire function). So, there is no need to
69374  * record regbases etc.
69375  */
69376 
69377  DUK_ASSERT(thr->catchstack[cat_idx].h_varname != NULL);
69378  duk_push_hstring(ctx, thr->catchstack[cat_idx].h_varname);
69379  duk_push_tval(ctx, thr->valstack + thr->catchstack[cat_idx].idx_base);
69380  duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_W); /* writable, not configurable */
69381 
69382  act = thr->callstack + thr->callstack_top - 1;
69383  act->lex_env = new_env;
69384  DUK_HOBJECT_INCREF(thr, new_env); /* reachable through activation */
69385 
69386  DUK_CAT_SET_LEXENV_ACTIVE(&thr->catchstack[cat_idx]);
69387 
69388  duk_pop(ctx);
69389 
69390  DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
69391  }
69392 
69393  DUK_CAT_CLEAR_CATCH_ENABLED(&thr->catchstack[cat_idx]);
69394 }
69395 
69396 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) {
69397  duk_activation *act;
69398 
69399  DUK_ASSERT(thr != NULL);
69400  DUK_ASSERT(tv_val_unstable != NULL);
69401 
69402  duk__set_catcher_regs(thr, cat_idx, tv_val_unstable, lj_type);
69403 
69404  duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* cat_idx catcher is kept, even for finally */
69405  duk_hthread_callstack_unwind(thr, thr->catchstack[cat_idx].callstack_index + 1);
69406 
69407  DUK_ASSERT(thr->callstack_top >= 1);
69408  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
69409  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
69410 
69411  duk__reconfig_valstack_ecma_catcher(thr, thr->callstack_top - 1, cat_idx);
69412 
69413  DUK_ASSERT(thr->callstack_top >= 1);
69414  act = thr->callstack + thr->callstack_top - 1;
69415  act->curr_pc = thr->catchstack[cat_idx].pc_base + 1; /* +1 = finally */
69416  act = NULL;
69417 
69418  DUK_CAT_CLEAR_FINALLY_ENABLED(&thr->catchstack[cat_idx]);
69419 }
69420 
69421 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_size_t cat_idx, duk_small_uint_t lj_type) {
69422  duk_activation *act;
69423 
69424  DUK_ASSERT(thr != NULL);
69425 
69426  DUK_ASSERT(thr->callstack_top >= 1);
69427  act = thr->callstack + thr->callstack_top - 1;
69428 
69429  DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
69430  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
69431 
69432  /* +0 = break, +1 = continue */
69433  act->curr_pc = thr->catchstack[cat_idx].pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
69434  act = NULL; /* invalidated */
69435 
69436  duk_hthread_catchstack_unwind(thr, cat_idx + 1); /* keep label catcher */
69437  /* no need to unwind callstack */
69438 
69439  /* valstack should not need changes */
69440 #if defined(DUK_USE_ASSERTIONS)
69441  DUK_ASSERT(thr->callstack_top >= 1);
69442  act = thr->callstack + thr->callstack_top - 1;
69443  DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
69444  (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
69445 #endif
69446 }
69447 
69448 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
69449  * when a RETURN opcode terminates a thread and yields to the resumer.
69450  */
69451 #if defined(DUK_USE_COROUTINE_SUPPORT)
69452 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_size_t act_idx, duk_tval *tv_val_unstable) {
69453  duk_tval *tv1;
69454 
69455  DUK_ASSERT(thr != NULL);
69456  DUK_ASSERT(resumer != NULL);
69457  DUK_ASSERT(tv_val_unstable != NULL);
69458  DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + act_idx) != NULL);
69459  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack + act_idx))); /* resume caller must be an ecmascript func */
69460 
69461  tv1 = resumer->valstack + resumer->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.resume() */
69462  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable); /* side effects */
69463 
69464  duk_hthread_callstack_unwind(resumer, act_idx + 1); /* unwind to 'resume' caller */
69465 
69466  /* no need to unwind catchstack */
69467  duk__reconfig_valstack_ecma_return(resumer, act_idx);
69468 
69469  /* caller must change active thread, and set thr->resumer to NULL */
69470 }
69471 #endif /* DUK_USE_COROUTINE_SUPPORT */
69472 
69473 DUK_LOCAL
69474 duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
69475  duk_hthread *entry_thread,
69476  duk_size_t entry_callstack_top) {
69477  duk_size_t entry_callstack_index;
69478  duk_small_uint_t retval = DUK__LONGJMP_RESTART;
69479 
69480  DUK_ASSERT(thr != NULL);
69481  DUK_ASSERT(entry_thread != NULL);
69482  DUK_ASSERT(entry_callstack_top > 0); /* guarantees entry_callstack_top - 1 >= 0 */
69483 
69484  entry_callstack_index = entry_callstack_top - 1;
69485 
69486  /* 'thr' is the current thread, as no-one resumes except us and we
69487  * switch 'thr' in that case.
69488  */
69489  DUK_ASSERT(thr == thr->heap->curr_thread);
69490 
69491  /*
69492  * (Re)try handling the longjmp.
69493  *
69494  * A longjmp handler may convert the longjmp to a different type and
69495  * "virtually" rethrow by goto'ing to 'check_longjmp'. Before the goto,
69496  * the following must be updated:
69497  * - the heap 'lj' state
69498  * - 'thr' must reflect the "throwing" thread
69499  */
69500 
69501  check_longjmp:
69502 
69503  DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
69504  (long) thr->heap->lj.type,
69505  (duk_tval *) &thr->heap->lj.value1,
69506  (duk_tval *) &thr->heap->lj.value2,
69507  (long) thr->heap->lj.iserror));
69508 
69509  switch (thr->heap->lj.type) {
69510 
69511 #if defined(DUK_USE_COROUTINE_SUPPORT)
69512  case DUK_LJ_TYPE_RESUME: {
69513  /*
69514  * Note: lj.value1 is 'value', lj.value2 is 'resumee'.
69515  * This differs from YIELD.
69516  */
69517 
69518  duk_tval *tv;
69519  duk_tval *tv2;
69520  duk_size_t act_idx;
69521  duk_hthread *resumee;
69522 
69523  /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
69524 
69525  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged by Duktape.Thread.resume() */
69526  DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
69527  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
69528  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
69529  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_resume);
69530  DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
69531 
69532  tv = &thr->heap->lj.value2; /* resumee */
69533  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
69534  DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
69535  DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
69536  resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
69537 
69538  DUK_ASSERT(resumee != NULL);
69539  DUK_ASSERT(resumee->resumer == NULL);
69540  DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
69541  resumee->state == DUK_HTHREAD_STATE_YIELDED); /* checked by Duktape.Thread.resume() */
69542  DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
69543  resumee->callstack_top >= 2); /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */
69544  DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
69545  (DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1) != NULL &&
69546  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1)) &&
69547  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack + resumee->callstack_top - 1))->func == duk_bi_thread_yield));
69548  DUK_ASSERT_DISABLE(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
69549  (resumee->callstack + resumee->callstack_top - 2)->idx_retval >= 0); /* idx_retval unsigned */
69550  DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
69551  resumee->callstack_top == 0); /* INACTIVE: no activation, single function value on valstack */
69552 
69553  if (thr->heap->lj.iserror) {
69554  /*
69555  * Throw the error in the resumed thread's context; the
69556  * error value is pushed onto the resumee valstack.
69557  *
69558  * Note: the callstack of the target may empty in this case
69559  * too (i.e. the target thread has never been resumed). The
69560  * value stack will contain the initial function in that case,
69561  * which we simply ignore.
69562  */
69563 
69564  resumee->resumer = thr;
69565  resumee->state = DUK_HTHREAD_STATE_RUNNING;
69566  thr->state = DUK_HTHREAD_STATE_RESUMED;
69567  DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
69568  thr = resumee;
69569 
69570  thr->heap->lj.type = DUK_LJ_TYPE_THROW;
69571 
69572  /* thr->heap->lj.value1 is already the value to throw */
69573  /* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
69574 
69575  DUK_ASSERT(thr->heap->lj.iserror); /* already set */
69576 
69577  DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
69578  goto check_longjmp;
69579  } else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
69580  act_idx = resumee->callstack_top - 2; /* Ecmascript function */
69581  DUK_ASSERT_DISABLE(resumee->callstack[act_idx].idx_retval >= 0); /* unsigned */
69582 
69583  tv = resumee->valstack + resumee->callstack[act_idx].idx_retval; /* return value from Duktape.Thread.yield() */
69584  DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
69585  tv2 = &thr->heap->lj.value1;
69586  DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2); /* side effects */
69587 
69588  duk_hthread_callstack_unwind(resumee, act_idx + 1); /* unwind to 'yield' caller */
69589 
69590  /* no need to unwind catchstack */
69591 
69592  duk__reconfig_valstack_ecma_return(resumee, act_idx);
69593 
69594  resumee->resumer = thr;
69595  resumee->state = DUK_HTHREAD_STATE_RUNNING;
69596  thr->state = DUK_HTHREAD_STATE_RESUMED;
69597  DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
69598 #if 0
69599  thr = resumee; /* not needed, as we exit right away */
69600 #endif
69601  DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
69602  retval = DUK__LONGJMP_RESTART;
69603  goto wipe_and_return;
69604  } else {
69605  duk_small_uint_t call_flags;
69606  duk_bool_t setup_rc;
69607 
69608  /* resumee: [... initial_func] (currently actually: [initial_func]) */
69609 
69610  duk_push_undefined((duk_context *) resumee);
69611  tv = &thr->heap->lj.value1;
69612  duk_push_tval((duk_context *) resumee, tv);
69613 
69614  /* resumee: [... initial_func undefined(= this) resume_value ] */
69615 
69616  call_flags = DUK_CALL_FLAG_IS_RESUME; /* is resume, not a tail call */
69617 
69618  setup_rc = duk_handle_ecma_call_setup(resumee,
69619  1, /* num_stack_args */
69620  call_flags); /* call_flags */
69621  if (setup_rc == 0) {
69622  /* This shouldn't happen; Duktape.Thread.resume()
69623  * should make sure of that. If it does happen
69624  * this internal error will propagate out of the
69625  * executor which can be quite misleading.
69626  */
69627  DUK_ERROR_INTERNAL(thr);
69628  }
69629 
69630  resumee->resumer = thr;
69631  resumee->state = DUK_HTHREAD_STATE_RUNNING;
69632  thr->state = DUK_HTHREAD_STATE_RESUMED;
69633  DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
69634 #if 0
69635  thr = resumee; /* not needed, as we exit right away */
69636 #endif
69637  DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
69638  retval = DUK__LONGJMP_RESTART;
69639  goto wipe_and_return;
69640  }
69641  DUK_UNREACHABLE();
69642  break; /* never here */
69643  }
69644 
69645  case DUK_LJ_TYPE_YIELD: {
69646  /*
69647  * Currently only allowed only if yielding thread has only
69648  * Ecmascript activations (except for the Duktape.Thread.yield()
69649  * call at the callstack top) and none of them constructor
69650  * calls.
69651  *
69652  * This excludes the 'entry' thread which will always have
69653  * a preventcount > 0.
69654  */
69655 
69656  duk_hthread *resumer;
69657 
69658  /* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
69659 
69660  DUK_ASSERT(thr != entry_thread); /* Duktape.Thread.yield() should prevent */
69661  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING); /* unchanged from Duktape.Thread.yield() */
69662  DUK_ASSERT(thr->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.yield() activation */
69663  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL &&
69664  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)) &&
69665  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1))->func == duk_bi_thread_yield);
69666  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2) != NULL &&
69667  DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* an Ecmascript function */
69668  DUK_ASSERT_DISABLE((thr->callstack + thr->callstack_top - 2)->idx_retval >= 0); /* unsigned */
69669 
69670  resumer = thr->resumer;
69671 
69672  DUK_ASSERT(resumer != NULL);
69673  DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED); /* written by a previous RESUME handling */
69674  DUK_ASSERT(resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
69675  DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1) != NULL &&
69676  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1)) &&
69677  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 1))->func == duk_bi_thread_resume);
69678  DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2) != NULL &&
69679  DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack + resumer->callstack_top - 2))); /* an Ecmascript function */
69680  DUK_ASSERT_DISABLE((resumer->callstack + resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
69681 
69682  if (thr->heap->lj.iserror) {
69683  thr->state = DUK_HTHREAD_STATE_YIELDED;
69684  thr->resumer = NULL;
69685  resumer->state = DUK_HTHREAD_STATE_RUNNING;
69686  DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
69687  thr = resumer;
69688 
69689  thr->heap->lj.type = DUK_LJ_TYPE_THROW;
69690  /* lj.value1 is already set */
69691  DUK_ASSERT(thr->heap->lj.iserror); /* already set */
69692 
69693  DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
69694  goto check_longjmp;
69695  } else {
69696  duk__handle_yield(thr, resumer, resumer->callstack_top - 2, &thr->heap->lj.value1);
69697 
69698  thr->state = DUK_HTHREAD_STATE_YIELDED;
69699  thr->resumer = NULL;
69700  resumer->state = DUK_HTHREAD_STATE_RUNNING;
69701  DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
69702 #if 0
69703  thr = resumer; /* not needed, as we exit right away */
69704 #endif
69705 
69706  DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
69707  retval = DUK__LONGJMP_RESTART;
69708  goto wipe_and_return;
69709  }
69710  DUK_UNREACHABLE();
69711  break; /* never here */
69712  }
69713 #endif /* DUK_USE_COROUTINE_SUPPORT */
69714 
69715  case DUK_LJ_TYPE_THROW: {
69716  /*
69717  * Three possible outcomes:
69718  * * A try or finally catcher is found => resume there.
69719  * (or)
69720  * * The error propagates to the bytecode executor entry
69721  * level (and we're in the entry thread) => rethrow
69722  * with a new longjmp(), after restoring the previous
69723  * catchpoint.
69724  * * The error is not caught in the current thread, so
69725  * the thread finishes with an error. This works like
69726  * a yielded error, except that the thread is finished
69727  * and can no longer be resumed. (There is always a
69728  * resumer in this case.)
69729  *
69730  * Note: until we hit the entry level, there can only be
69731  * Ecmascript activations.
69732  */
69733 
69734  duk_catcher *cat;
69735  duk_hthread *resumer;
69736 
69737  cat = thr->catchstack + thr->catchstack_top - 1;
69738  while (cat >= thr->catchstack) {
69739  if (thr == entry_thread &&
69740  cat->callstack_index < entry_callstack_index) {
69741  /* entry level reached */
69742  break;
69743  }
69744 
69745  if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
69746  DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
69747 
69748  duk__handle_catch(thr,
69749  cat - thr->catchstack,
69750  &thr->heap->lj.value1,
69751  DUK_LJ_TYPE_THROW);
69752 
69753  DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
69754  retval = DUK__LONGJMP_RESTART;
69755  goto wipe_and_return;
69756  }
69757 
69758  if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69759  DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
69760  DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
69761 
69762  duk__handle_finally(thr,
69763  cat - thr->catchstack,
69764  &thr->heap->lj.value1,
69765  DUK_LJ_TYPE_THROW);
69766 
69767  DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
69768  retval = DUK__LONGJMP_RESTART;
69769  goto wipe_and_return;
69770  }
69771 
69772  cat--;
69773  }
69774 
69775  if (thr == entry_thread) {
69776  /* not caught by anything before entry level; rethrow and let the
69777  * final catcher unwind everything
69778  */
69779 #if 0
69780  duk_hthread_catchstack_unwind(thr, (cat - thr->catchstack) + 1); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
69781  duk_hthread_callstack_unwind(thr, entry_callstack_index + 1);
69782 
69783 #endif
69784  DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
69785  retval = DUK__LONGJMP_RETHROW;
69786  goto just_return;
69787  /* Note: MUST NOT wipe_and_return here, as heap->lj must remain intact */
69788  }
69789 
69790  DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
69791 
69792  /* not caught by current thread, thread terminates (yield error to resumer);
69793  * note that this may cause a cascade if the resumer terminates with an uncaught
69794  * exception etc (this is OK, but needs careful testing)
69795  */
69796 
69797  DUK_ASSERT(thr->resumer != NULL);
69798  DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
69799  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
69800  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
69801  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
69802  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
69803  DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
69804 
69805  resumer = thr->resumer;
69806 
69807  /* reset longjmp */
69808 
69809  DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW); /* already set */
69810  /* lj.value1 already set */
69811 
69812  duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
69813  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
69814 
69815  thr->resumer = NULL;
69816  resumer->state = DUK_HTHREAD_STATE_RUNNING;
69817  DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
69818  thr = resumer;
69819  goto check_longjmp;
69820  }
69821 
69822  case DUK_LJ_TYPE_BREAK: /* pseudotypes, not used in actual longjmps */
69823  case DUK_LJ_TYPE_CONTINUE:
69824  case DUK_LJ_TYPE_RETURN:
69825  case DUK_LJ_TYPE_NORMAL:
69826  default: {
69827  /* should never happen, but be robust */
69828  DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
69829  goto convert_to_internal_error;
69830  }
69831 
69832  } /* end switch */
69833 
69834  DUK_UNREACHABLE();
69835 
69836  wipe_and_return:
69837  /* this is not strictly necessary, but helps debugging */
69838  thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
69839  thr->heap->lj.iserror = 0;
69840 
69841  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1); /* side effects */
69842  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2); /* side effects */
69843 
69844  just_return:
69845  return retval;
69846 
69847  convert_to_internal_error:
69848  /* This could also be thrown internally (set the error, goto check_longjmp),
69849  * but it's better for internal errors to bubble outwards so that we won't
69850  * infinite loop in this catchpoint.
69851  */
69852  DUK_ERROR_INTERNAL(thr);
69853  DUK_UNREACHABLE();
69854  return retval;
69855 }
69856 
69857 /* Handle a BREAK/CONTINUE opcode. Avoid using longjmp() for BREAK/CONTINUE
69858  * handling because it has a measurable performance impact in ordinary
69859  * environments and an extreme impact in Emscripten (GH-342).
69860  */
69861 DUK_LOCAL void duk__handle_break_or_continue(duk_hthread *thr,
69862  duk_uint_t label_id,
69863  duk_small_uint_t lj_type) {
69864  duk_catcher *cat;
69865  duk_size_t orig_callstack_index;
69866 
69867  DUK_ASSERT(thr != NULL);
69868 
69869  /*
69870  * Find a matching label catcher or 'finally' catcher in
69871  * the same function.
69872  *
69873  * A label catcher must always exist and will match unless
69874  * a 'finally' captures the break/continue first. It is the
69875  * compiler's responsibility to ensure that labels are used
69876  * correctly.
69877  */
69878 
69879  /* Note: thr->catchstack_top may be 0, so that cat < thr->catchstack
69880  * initially. This is OK and intended.
69881  */
69882  cat = thr->catchstack + thr->catchstack_top - 1;
69883  DUK_ASSERT(thr->callstack_top > 0);
69884  orig_callstack_index = thr->callstack_top - 1;
69885 
69886  DUK_DDD(DUK_DDDPRINT("handling break/continue with label=%ld, callstack index=%ld",
69887  (long) label_id, (long) cat->callstack_index));
69888 
69889  while (cat >= thr->catchstack) {
69890  if (cat->callstack_index != orig_callstack_index) {
69891  break;
69892  }
69893  DUK_DDD(DUK_DDDPRINT("considering catcher %ld: type=%ld label=%ld",
69894  (long) (cat - thr->catchstack),
69895  (long) DUK_CAT_GET_TYPE(cat),
69896  (long) DUK_CAT_GET_LABEL(cat)));
69897 
69898  if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
69899  DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69900  duk_size_t cat_idx;
69901  duk_tval tv_tmp;
69902 
69903  cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
69904 
69905  DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
69906  duk__handle_finally(thr, cat_idx, &tv_tmp, lj_type);
69907 
69908  DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
69909  return;
69910  }
69911  if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
69912  (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
69913  duk_size_t cat_idx;
69914 
69915  cat_idx = (duk_size_t) (cat - thr->catchstack);
69916  duk__handle_label(thr, cat_idx, lj_type);
69917 
69918  DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
69919  return;
69920  }
69921  cat--;
69922  }
69923 
69924  /* should never happen, but be robust */
69925  DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
69926  DUK_ERROR_INTERNAL(thr);
69927  return;
69928 }
69929 
69930 /* Handle a RETURN opcode. Avoid using longjmp() for return handling because
69931  * it has a measurable performance impact in ordinary environments and an extreme
69932  * impact in Emscripten (GH-342). Return value is on value stack top.
69933  */
69934 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
69935  duk_hthread *entry_thread,
69936  duk_size_t entry_callstack_top) {
69937  duk_tval *tv1;
69938  duk_tval *tv2;
69939 #if defined(DUK_USE_COROUTINE_SUPPORT)
69940  duk_hthread *resumer;
69941 #endif
69942  duk_catcher *cat;
69943  duk_size_t new_cat_top;
69944  duk_size_t orig_callstack_index;
69945 
69946  /* We can directly access value stack here. */
69947 
69948  DUK_ASSERT(thr != NULL);
69949  DUK_ASSERT(entry_thread != NULL);
69950  DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
69951  tv1 = thr->valstack_top - 1;
69952  DUK_TVAL_CHKFAST_INPLACE_FAST(tv1); /* fastint downgrade check for return values */
69953 
69954  /*
69955  * Four possible outcomes:
69956  *
69957  * 1. A 'finally' in the same function catches the 'return'.
69958  * It may continue to propagate when 'finally' is finished,
69959  * or it may be neutralized by 'finally' (both handled by
69960  * ENDFIN).
69961  *
69962  * 2. The return happens at the entry level of the bytecode
69963  * executor, so return from the executor (in C stack).
69964  *
69965  * 3. There is a calling (Ecmascript) activation in the call
69966  * stack => return to it, in the same executor instance.
69967  *
69968  * 4. There is no calling activation, and the thread is
69969  * terminated. There is always a resumer in this case,
69970  * which gets the return value similarly to a 'yield'
69971  * (except that the current thread can no longer be
69972  * resumed).
69973  */
69974 
69975  DUK_ASSERT(thr != NULL);
69976  DUK_ASSERT(thr->callstack_top >= 1);
69977  DUK_ASSERT(thr->catchstack != NULL);
69978 
69979  /* XXX: does not work if thr->catchstack is NULL */
69980  /* XXX: does not work if thr->catchstack is allocated but lowest pointer */
69981 
69982  cat = thr->catchstack + thr->catchstack_top - 1; /* may be < thr->catchstack initially */
69983  DUK_ASSERT(thr->callstack_top > 0); /* ensures callstack_top - 1 >= 0 */
69984  orig_callstack_index = thr->callstack_top - 1;
69985 
69986  while (cat >= thr->catchstack) {
69987  if (cat->callstack_index != orig_callstack_index) {
69988  break;
69989  }
69990  if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
69991  DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
69992  duk_size_t cat_idx;
69993 
69994  cat_idx = (duk_size_t) (cat - thr->catchstack); /* get before side effects */
69995 
69996  DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
69997  duk__handle_finally(thr, cat_idx, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
69998 
69999  DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
70000  return DUK__RETHAND_RESTART;
70001  }
70002  cat--;
70003  }
70004  /* If out of catchstack, cat = thr->catchstack - 1;
70005  * new_cat_top will be 0 in that case.
70006  */
70007  new_cat_top = (duk_size_t) ((cat + 1) - thr->catchstack);
70008  cat = NULL; /* avoid referencing, invalidated */
70009 
70010  DUK_DDD(DUK_DDDPRINT("no catcher in catch stack, return to calling activation / yield"));
70011 
70012  if (thr == entry_thread &&
70013  thr->callstack_top == entry_callstack_top) {
70014  /* Return to the bytecode executor caller which will unwind stacks.
70015  * Return value is already on the stack top: [ ... retval ].
70016  */
70017 
70018  /* XXX: could unwind catchstack here, so that call handling
70019  * didn't need to do that?
70020  */
70021  DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
70022  return DUK__RETHAND_FINISHED;
70023  }
70024 
70025  if (thr->callstack_top >= 2) {
70026  /* There is a caller; it MUST be an Ecmascript caller (otherwise it would
70027  * match entry level check)
70028  */
70029 
70030  DUK_DDD(DUK_DDDPRINT("return to Ecmascript caller, idx_retval=%ld, lj_value1=%!T",
70031  (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
70032  (duk_tval *) &thr->heap->lj.value1));
70033 
70034  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 2))); /* must be ecmascript */
70035 
70036  tv1 = thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval;
70037  DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
70038  tv2 = thr->valstack_top - 1;
70039  DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2); /* side effects */
70040 
70041  DUK_DDD(DUK_DDDPRINT("return value at idx_retval=%ld is %!T",
70042  (long) (thr->callstack + thr->callstack_top - 2)->idx_retval,
70043  (duk_tval *) (thr->valstack + (thr->callstack + thr->callstack_top - 2)->idx_retval)));
70044 
70045  duk_hthread_catchstack_unwind(thr, new_cat_top); /* leave 'cat' as top catcher (also works if catchstack exhausted) */
70046  duk_hthread_callstack_unwind(thr, thr->callstack_top - 1);
70047  duk__reconfig_valstack_ecma_return(thr, thr->callstack_top - 1);
70048 
70049  DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
70050  return DUK__RETHAND_RESTART;
70051  }
70052 
70053 #if defined(DUK_USE_COROUTINE_SUPPORT)
70054  DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
70055 
70056  DUK_ASSERT(thr->resumer != NULL);
70057  DUK_ASSERT(thr->resumer->callstack_top >= 2); /* Ecmascript activation + Duktape.Thread.resume() activation */
70058  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1) != NULL &&
70059  DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1)) &&
70060  ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 1))->func == duk_bi_thread_resume); /* Duktape.Thread.resume() */
70061  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2) != NULL &&
70062  DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack + thr->resumer->callstack_top - 2))); /* an Ecmascript function */
70063  DUK_ASSERT_DISABLE((thr->resumer->callstack + thr->resumer->callstack_top - 2)->idx_retval >= 0); /* unsigned */
70064  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
70065  DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
70066 
70067  resumer = thr->resumer;
70068 
70069  /* Share yield longjmp handler. */
70070  DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
70071  duk__handle_yield(thr, resumer, resumer->callstack_top - 2, thr->valstack_top - 1);
70072 
70073  duk_hthread_terminate(thr); /* updates thread state, minimizes its allocations */
70074  DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
70075 
70076  thr->resumer = NULL;
70077  resumer->state = DUK_HTHREAD_STATE_RUNNING;
70078  DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
70079 #if 0
70080  thr = resumer; /* not needed */
70081 #endif
70082 
70083  DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
70084  return DUK__RETHAND_RESTART;
70085 #else
70086  /* Without coroutine support this case should never happen. */
70087  DUK_ERROR_INTERNAL(thr);
70088  return DUK__RETHAND_FINISHED; /* not executed */
70089 #endif
70090 }
70091 
70092 /*
70093  * Executor interrupt handling
70094  *
70095  * The handler is called whenever the interrupt countdown reaches zero
70096  * (or below). The handler must perform whatever checks are activated,
70097  * e.g. check for cumulative step count to impose an execution step
70098  * limit or check for breakpoints or other debugger interaction.
70099  *
70100  * When the actions are done, the handler must reinit the interrupt
70101  * init and counter values. The 'init' value must indicate how many
70102  * bytecode instructions are executed before the next interrupt. The
70103  * counter must interface with the bytecode executor loop. Concretely,
70104  * the new init value is normally one higher than the new counter value.
70105  * For instance, to execute exactly one bytecode instruction the init
70106  * value is set to 1 and the counter to 0. If an error is thrown by the
70107  * interrupt handler, the counters are set to the same value (e.g. both
70108  * to 0 to cause an interrupt when the next bytecode instruction is about
70109  * to be executed after error handling).
70110  *
70111  * Maintaining the init/counter value properly is important for accurate
70112  * behavior. For instance, executor step limit needs a cumulative step
70113  * count which is simply computed as a sum of 'init' values. This must
70114  * work accurately even when single stepping.
70115  */
70116 
70117 #if defined(DUK_USE_INTERRUPT_COUNTER)
70118 
70119 #define DUK__INT_NOACTION 0 /* no specific action, resume normal execution */
70120 #define DUK__INT_RESTART 1 /* must "goto restart_execution", e.g. breakpoints changed */
70121 
70122 #if defined(DUK_USE_DEBUGGER_SUPPORT)
70123 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
70124  duk_context *ctx;
70125  duk_activation *act;
70126  duk_breakpoint *bp;
70127  duk_breakpoint **bp_active;
70128  duk_uint_fast32_t line = 0;
70129  duk_bool_t process_messages;
70130  duk_bool_t processed_messages = 0;
70131 
70132  DUK_ASSERT(thr->heap->dbg_processing == 0); /* don't re-enter e.g. during Eval */
70133 
70134  ctx = (duk_context *) thr;
70135  act = thr->callstack + thr->callstack_top - 1;
70136 
70137  /* It might seem that replacing 'thr->heap' with just 'heap' below
70138  * might be a good idea, but it increases code size slightly
70139  * (probably due to unnecessary spilling) at least on x64.
70140  */
70141 
70142  /*
70143  * Breakpoint and step state checks
70144  */
70145 
70146  if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
70147  (thr->heap->dbg_step_thread == thr &&
70148  thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
70149  line = duk_debug_curr_line(thr);
70150 
70151  if (act->prev_line != line) {
70152  /* Stepped? Step out is handled by callstack unwind. */
70153  if ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
70154  thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
70155  (thr->heap->dbg_step_thread == thr) &&
70156  (thr->heap->dbg_step_csindex == thr->callstack_top - 1) &&
70157  (line != thr->heap->dbg_step_startline)) {
70158  DUK_D(DUK_DPRINT("STEP STATE TRIGGERED PAUSE at line %ld",
70159  (long) line));
70160 
70161  DUK_HEAP_SET_PAUSED(thr->heap);
70162  }
70163 
70164  /* Check for breakpoints only on line transition.
70165  * Breakpoint is triggered when we enter the target
70166  * line from a different line, and the previous line
70167  * was within the same function.
70168  *
70169  * This condition is tricky: the condition used to be
70170  * that transition to -or across- the breakpoint line
70171  * triggered the breakpoint. This seems intuitively
70172  * better because it handles breakpoints on lines with
70173  * no emitted opcodes; but this leads to the issue
70174  * described in: https://github.com/svaarala/duktape/issues/263.
70175  */
70176  bp_active = thr->heap->dbg_breakpoints_active;
70177  for (;;) {
70178  bp = *bp_active++;
70179  if (bp == NULL) {
70180  break;
70181  }
70182 
70183  DUK_ASSERT(bp->filename != NULL);
70184  if (act->prev_line != bp->line && line == bp->line) {
70185  DUK_D(DUK_DPRINT("BREAKPOINT TRIGGERED at %!O:%ld",
70186  (duk_heaphdr *) bp->filename, (long) bp->line));
70187 
70188  DUK_HEAP_SET_PAUSED(thr->heap);
70189  }
70190  }
70191  } else {
70192  ;
70193  }
70194 
70195  act->prev_line = line;
70196  }
70197 
70198  /*
70199  * Rate limit check for sending status update or peeking into
70200  * the debug transport. Both can be expensive operations that
70201  * we don't want to do on every opcode.
70202  *
70203  * Making sure the interval remains reasonable on a wide variety
70204  * of targets and bytecode is difficult without a timestamp, so
70205  * we use a Date-provided timestamp for the rate limit check.
70206  * But since it's also expensive to get a timestamp, a bytecode
70207  * counter is used to rate limit getting timestamps.
70208  */
70209 
70210  process_messages = 0;
70211  if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
70212  /* Enter message processing loop for sending Status notifys and
70213  * to finish a pending detach.
70214  */
70215  process_messages = 1;
70216  }
70217 
70218  /* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
70219  thr->heap->dbg_exec_counter += thr->interrupt_init;
70220  if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
70221  /* Overflow of the execution counter is fine and doesn't break
70222  * anything here.
70223  */
70224 
70225  duk_double_t now, diff_last;
70226 
70227  thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
70228  now = DUK_USE_DATE_GET_NOW(ctx);
70229 
70230  diff_last = now - thr->heap->dbg_last_time;
70231  if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
70232  /* Negative value checked so that a "time jump" works
70233  * reasonably.
70234  *
70235  * Same interval is now used for status sending and
70236  * peeking.
70237  */
70238 
70239  thr->heap->dbg_last_time = now;
70240  thr->heap->dbg_state_dirty = 1;
70241  process_messages = 1;
70242  }
70243  }
70244 
70245  /*
70246  * Process messages and send status if necessary.
70247  *
70248  * If we're paused, we'll block for new messages. If we're not
70249  * paused, we'll process anything we can peek but won't block
70250  * for more. Detach (and re-attach) handling is all localized
70251  * to duk_debug_process_messages() too.
70252  *
70253  * Debugger writes outside the message loop may cause debugger
70254  * detach1 phase to run, after which dbg_read_cb == NULL and
70255  * dbg_detaching != 0. The message loop will finish the detach
70256  * by running detach2 phase, so enter the message loop also when
70257  * detaching.
70258  */
70259 
70260  act = NULL; /* may be changed */
70261  if (process_messages) {
70262  DUK_ASSERT(thr->heap->dbg_processing == 0);
70263  processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
70264  DUK_ASSERT(thr->heap->dbg_processing == 0);
70265  }
70266 
70267  /* Continue checked execution if there are breakpoints or we're stepping.
70268  * Also use checked execution if paused flag is active - it shouldn't be
70269  * because the debug message loop shouldn't terminate if it was. Step out
70270  * is handled by callstack unwind and doesn't need checked execution.
70271  * Note that debugger may have detached due to error or explicit request
70272  * above, so we must recheck attach status.
70273  */
70274 
70275  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
70276  act = thr->callstack + thr->callstack_top - 1; /* relookup, may have changed */
70277  if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
70278  ((thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO ||
70279  thr->heap->dbg_step_type == DUK_STEP_TYPE_OVER) &&
70280  thr->heap->dbg_step_thread == thr &&
70281  thr->heap->dbg_step_csindex == thr->callstack_top - 1) ||
70282  DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
70283  *out_immediate = 1;
70284  }
70285 
70286  /* If we processed any debug messages breakpoints may have
70287  * changed; restart execution to re-check active breakpoints.
70288  */
70289  if (processed_messages) {
70290  DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
70291  *out_interrupt_retval = DUK__INT_RESTART;
70292  }
70293  } else {
70294  DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
70295  }
70296 }
70297 #endif /* DUK_USE_DEBUGGER_SUPPORT */
70298 
70299 DUK_LOCAL duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
70300  duk_int_t ctr;
70301  duk_activation *act;
70302  duk_hcompfunc *fun;
70303  duk_bool_t immediate = 0;
70304  duk_small_uint_t retval;
70305 
70306  DUK_ASSERT(thr != NULL);
70307  DUK_ASSERT(thr->heap != NULL);
70308  DUK_ASSERT(thr->callstack != NULL);
70309  DUK_ASSERT(thr->callstack_top > 0);
70310 
70311 #if defined(DUK_USE_DEBUG)
70312  thr->heap->inst_count_interrupt += thr->interrupt_init;
70313  DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
70314  "instruction counts: executor=%ld, interrupt=%ld",
70315  (long) thr->interrupt_counter, (long) thr->interrupt_init,
70316  (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
70317 #endif
70318 
70319  retval = DUK__INT_NOACTION;
70320  ctr = DUK_HTHREAD_INTCTR_DEFAULT;
70321 
70322  /*
70323  * Avoid nested calls. Concretely this happens during debugging, e.g.
70324  * when we eval() an expression.
70325  *
70326  * Also don't interrupt if we're currently doing debug processing
70327  * (which can be initiated outside the bytecode executor) as this
70328  * may cause the debugger to be called recursively. Check required
70329  * for correct operation of throw intercept and other "exotic" halting
70330  * scenarios.
70331  */
70332 
70333 #if defined(DUK_USE_DEBUGGER_SUPPORT)
70334  if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
70335 #else
70336  if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
70337 #endif
70338  DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
70339 
70340  /* Set a high interrupt counter; the original executor
70341  * interrupt invocation will rewrite before exiting.
70342  */
70343  thr->interrupt_init = ctr;
70344  thr->interrupt_counter = ctr - 1;
70345  return DUK__INT_NOACTION;
70346  }
70347  DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
70348 
70349  act = thr->callstack + thr->callstack_top - 1;
70350 
70351  fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
70352  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
70353 
70354  DUK_UNREF(fun);
70355 
70356 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
70357  /*
70358  * Execution timeout check
70359  */
70360 
70361  if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
70362  /* Keep throwing an error whenever we get here. The unusual values
70363  * are set this way because no instruction is ever executed, we just
70364  * throw an error until all try/catch/finally and other catchpoints
70365  * have been exhausted. Duktape/C code gets control at each protected
70366  * call but whenever it enters back into Duktape the RangeError gets
70367  * raised. User exec timeout check must consistently indicate a timeout
70368  * until we've fully bubbled out of Duktape.
70369  */
70370  DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
70371  thr->interrupt_init = 0;
70372  thr->interrupt_counter = 0;
70373  DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
70374  DUK_ERROR_RANGE(thr, "execution timeout");
70375  }
70376 #endif /* DUK_USE_EXEC_TIMEOUT_CHECK */
70377 
70378 #if defined(DUK_USE_DEBUGGER_SUPPORT)
70379  if (!thr->heap->dbg_processing &&
70380  (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
70381  /* Avoid recursive re-entry; enter when we're attached or
70382  * detaching (to finish off the pending detach).
70383  */
70384  duk__interrupt_handle_debugger(thr, &immediate, &retval);
70385  act = thr->callstack + thr->callstack_top - 1; /* relookup if changed */
70386  DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
70387  }
70388 #endif /* DUK_USE_DEBUGGER_SUPPORT */
70389 
70390  /*
70391  * Update the interrupt counter
70392  */
70393 
70394  if (immediate) {
70395  /* Cause an interrupt after executing one instruction. */
70396  ctr = 1;
70397  }
70398 
70399  /* The counter value is one less than the init value: init value should
70400  * indicate how many instructions are executed before interrupt. To
70401  * execute 1 instruction (after interrupt handler return), counter must
70402  * be 0.
70403  */
70404  DUK_ASSERT(ctr >= 1);
70405  thr->interrupt_init = ctr;
70406  thr->interrupt_counter = ctr - 1;
70407  DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
70408 
70409  return retval;
70410 }
70411 #endif /* DUK_USE_INTERRUPT_COUNTER */
70412 
70413 /*
70414  * Debugger handling for executor restart
70415  *
70416  * Check for breakpoints, stepping, etc, and figure out if we should execute
70417  * in checked or normal mode. Note that we can't do this when an activation
70418  * is created, because breakpoint status (and stepping status) may change
70419  * later, so we must recheck every time we're executing an activation.
70420  * This primitive should be side effect free to avoid changes during check.
70421  */
70422 
70423 #if defined(DUK_USE_DEBUGGER_SUPPORT)
70424 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
70425  duk_heap *heap;
70426  duk_tval *tv_tmp;
70427  duk_hstring *filename;
70428  duk_small_uint_t bp_idx;
70429  duk_breakpoint **bp_active;
70430 
70431  DUK_ASSERT(thr != NULL);
70432  DUK_ASSERT(act != NULL);
70433  DUK_ASSERT(fun != NULL);
70434 
70435  heap = thr->heap;
70436  bp_active = heap->dbg_breakpoints_active;
70437  act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
70438 
70439  tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
70440  if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
70441  filename = DUK_TVAL_GET_STRING(tv_tmp);
70442 
70443  /* Figure out all active breakpoints. A breakpoint is
70444  * considered active if the current function's fileName
70445  * matches the breakpoint's fileName, AND there is no
70446  * inner function that has matching line numbers
70447  * (otherwise a breakpoint would be triggered both
70448  * inside and outside of the inner function which would
70449  * be confusing). Example:
70450  *
70451  * function foo() {
70452  * print('foo');
70453  * function bar() { <-. breakpoints in these
70454  * print('bar'); | lines should not affect
70455  * } <-' foo() execution
70456  * bar();
70457  * }
70458  *
70459  * We need a few things that are only available when
70460  * debugger support is enabled: (1) a line range for
70461  * each function, and (2) access to the function
70462  * template to access the inner functions (and their
70463  * line ranges).
70464  *
70465  * It's important to have a narrow match for active
70466  * breakpoints so that we don't enter checked execution
70467  * when that's not necessary. For instance, if we're
70468  * running inside a certain function and there's
70469  * breakpoint outside in (after the call site), we
70470  * don't want to slow down execution of the function.
70471  */
70472 
70473  for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
70474  duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
70475  duk_hobject **funcs, **funcs_end;
70476  duk_hcompfunc *inner_fun;
70477  duk_bool_t bp_match;
70478 
70479  if (bp->filename == filename &&
70480  bp->line >= fun->start_line && bp->line <= fun->end_line) {
70481  bp_match = 1;
70482  DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
70483  "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
70484  DUK_HSTRING_GET_DATA(bp->filename),
70485  (long) bp->line,
70486  DUK_HSTRING_GET_DATA(filename),
70487  (long) bp->line,
70488  (long) fun->start_line,
70489  (long) fun->end_line));
70490 
70491  funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
70492  funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
70493  while (funcs != funcs_end) {
70494  inner_fun = (duk_hcompfunc *) *funcs;
70495  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
70496  if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
70497  DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
70498  bp_match = 0;
70499  break;
70500  }
70501  funcs++;
70502  }
70503 
70504  if (bp_match) {
70505  /* No need to check for size of bp_active list,
70506  * it's always larger than maximum number of
70507  * breakpoints.
70508  */
70509  act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
70510  *bp_active = heap->dbg_breakpoints + bp_idx;
70511  bp_active++;
70512  }
70513  }
70514  }
70515  }
70516 
70517  *bp_active = NULL; /* terminate */
70518 
70519  DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
70520 
70521  /* Force pause if we were doing "step into" in another activation. */
70522  if (thr->heap->dbg_step_thread != NULL &&
70523  thr->heap->dbg_step_type == DUK_STEP_TYPE_INTO &&
70524  (thr->heap->dbg_step_thread != thr ||
70525  thr->heap->dbg_step_csindex != thr->callstack_top - 1)) {
70526  DUK_D(DUK_DPRINT("STEP INTO ACTIVE, FORCE PAUSED"));
70527  DUK_HEAP_SET_PAUSED(thr->heap);
70528  }
70529 
70530  /* Force interrupt right away if we're paused or in "checked mode".
70531  * Step out is handled by callstack unwind.
70532  */
70533  if (act->flags & (DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
70534  DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
70535  (thr->heap->dbg_step_type != DUK_STEP_TYPE_OUT &&
70536  thr->heap->dbg_step_csindex == thr->callstack_top - 1)) {
70537  /* We'll need to interrupt early so recompute the init
70538  * counter to reflect the number of bytecode instructions
70539  * executed so that step counts for e.g. debugger rate
70540  * limiting are accurate.
70541  */
70542  DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
70543  thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
70544  thr->interrupt_counter = 0;
70545  }
70546 }
70547 #endif /* DUK_USE_DEBUGGER_SUPPORT */
70548 
70549 /*
70550  * Ecmascript bytecode executor.
70551  *
70552  * Resume execution for the current thread from its current activation.
70553  * Returns when execution would return from the entry level activation,
70554  * leaving a single return value on top of the stack. Function calls
70555  * and thread resumptions are handled internally. If an error occurs,
70556  * a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
70557  * setjmp() jmpbuf.
70558  *
70559  * Ecmascript function calls and coroutine resumptions are handled
70560  * internally (by the outer executor function) without recursive C calls.
70561  * Other function calls are handled using duk_handle_call(), increasing
70562  * C recursion depth.
70563  *
70564  * Abrupt completions (= long control tranfers) are handled either
70565  * directly by reconfiguring relevant stacks and restarting execution,
70566  * or via a longjmp. Longjmp-free handling is preferable for performance
70567  * (especially Emscripten performance), and is used for: break, continue,
70568  * and return.
70569  *
70570  * For more detailed notes, see doc/execution.rst.
70571  *
70572  * Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
70573  * and volatile.
70574  */
70575 
70576 /* Presence of 'fun' is config based, there's a marginal performance
70577  * difference and the best option is architecture dependent.
70578  */
70579 #if defined(DUK_USE_EXEC_FUN_LOCAL)
70580 #define DUK__FUN() fun
70581 #else
70582 #define DUK__FUN() ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack + (thr)->callstack_top - 1))
70583 #endif
70584 #define DUK__STRICT() (DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
70585 
70586 /* Reg/const access macros: these are very footprint and performance sensitive
70587  * so modify with care. Arguments are sometimes evaluated multiple times which
70588  * is not ideal.
70589  */
70590 #define DUK__REG(x) (*(thr->valstack_bottom + (x)))
70591 #define DUK__REGP(x) (thr->valstack_bottom + (x))
70592 #define DUK__CONST(x) (*(consts + (x)))
70593 #define DUK__CONSTP(x) (consts + (x))
70594 
70595 /* Reg/const access macros which take the 32-bit instruction and avoid an
70596  * explicit field decoding step by using shifts and masks. These must be
70597  * kept in sync with duk_js_bytecode.h. The shift/mask values are chosen
70598  * so that 'ins' can be shifted and masked and used as a -byte- offset
70599  * instead of a duk_tval offset which needs further shifting (which is an
70600  * issue on some, but not all, CPUs).
70601  */
70602 #define DUK__RCBIT_B DUK_BC_REGCONST_B
70603 #define DUK__RCBIT_C DUK_BC_REGCONST_C
70604 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
70605 #if defined(DUK_USE_PACKED_TVAL)
70606 #define DUK__TVAL_SHIFT 3 /* sizeof(duk_tval) == 8 */
70607 #else
70608 #define DUK__TVAL_SHIFT 4 /* sizeof(duk_tval) == 16; not always the case so also asserted for */
70609 #endif
70610 #define DUK__SHIFT_A (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
70611 #define DUK__SHIFT_B (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
70612 #define DUK__SHIFT_C (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
70613 #define DUK__SHIFT_BC (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
70614 #define DUK__MASK_A (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
70615 #define DUK__MASK_B (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
70616 #define DUK__MASK_C (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
70617 #define DUK__MASK_BC (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
70618 #define DUK__BYTEOFF_A(ins) (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
70619 #define DUK__BYTEOFF_B(ins) (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
70620 #define DUK__BYTEOFF_C(ins) (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
70621 #define DUK__BYTEOFF_BC(ins) (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
70622 
70623 #define DUK__REGP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
70624 #define DUK__REGP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
70625 #define DUK__REGP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
70626 #define DUK__REGP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
70627 #define DUK__CONSTP_A(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
70628 #define DUK__CONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
70629 #define DUK__CONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
70630 #define DUK__CONSTP_BC(ins) ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
70631 #define DUK__REGCONSTP_B(ins) ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
70632 #define DUK__REGCONSTP_C(ins) ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
70633 #else /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
70634 /* Safe alternatives, no assumption about duk_tval size. */
70635 #define DUK__REGP_A(ins) DUK__REGP(DUK_DEC_A((ins)))
70636 #define DUK__REGP_B(ins) DUK__REGP(DUK_DEC_B((ins)))
70637 #define DUK__REGP_C(ins) DUK__REGP(DUK_DEC_C((ins)))
70638 #define DUK__REGP_BC(ins) DUK__REGP(DUK_DEC_BC((ins)))
70639 #define DUK__CONSTP_A(ins) DUK__CONSTP(DUK_DEC_A((ins)))
70640 #define DUK__CONSTP_B(ins) DUK__CONSTP(DUK_DEC_B((ins)))
70641 #define DUK__CONSTP_C(ins) DUK__CONSTP(DUK_DEC_C((ins)))
70642 #define DUK__CONSTP_BC(ins) DUK__CONSTP(DUK_DEC_BC((ins)))
70643 #define DUK__REGCONSTP_B(ins) ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
70644 #define DUK__REGCONSTP_C(ins) ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
70645 #endif /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
70646 
70647 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
70648 #define DUK__INTERNAL_ERROR(msg) do { \
70649  DUK_ERROR_ERROR(thr, (msg)); \
70650  } while (0)
70651 #else
70652 #define DUK__INTERNAL_ERROR(msg) do { \
70653  goto internal_error; \
70654  } while (0)
70655 #endif
70656 
70657 #define DUK__SYNC_CURR_PC() do { \
70658  duk_activation *act; \
70659  act = thr->callstack + thr->callstack_top - 1; \
70660  act->curr_pc = curr_pc; \
70661  } while (0)
70662 #define DUK__SYNC_AND_NULL_CURR_PC() do { \
70663  duk_activation *act; \
70664  act = thr->callstack + thr->callstack_top - 1; \
70665  act->curr_pc = curr_pc; \
70666  thr->ptr_curr_pc = NULL; \
70667  } while (0)
70668 
70669 #if defined(DUK_USE_EXEC_PREFER_SIZE)
70670 #define DUK__LOOKUP_INDIRECT_INDEX(idx) do { \
70671  (idx) = (duk_uint_fast_t) duk_get_uint(ctx, (idx)); \
70672  } while (0)
70673 #elif defined(DUK_USE_FASTINT)
70674 #define DUK__LOOKUP_INDIRECT_INDEX(idx) do { \
70675  duk_tval *tv_ind; \
70676  tv_ind = DUK__REGP((idx)); \
70677  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
70678  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind)); /* compiler guarantees */ \
70679  (idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
70680  } while (0)
70681 #else
70682 #define DUK__LOOKUP_INDIRECT_INDEX(idx) do { \
70683  duk_tval *tv_ind; \
70684  tv_ind = DUK__REGP(idx); \
70685  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
70686  idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
70687  } while (0)
70688 #endif
70689 
70690 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
70691  duk_hthread *entry_thread,
70692  duk_size_t entry_callstack_top,
70693  duk_int_t entry_call_recursion_depth,
70694  duk_jmpbuf *entry_jmpbuf_ptr) {
70695  duk_small_uint_t lj_ret;
70696 
70697  /* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
70698  * before longjmp.
70699  */
70700  DUK_ASSERT(heap->curr_thread != NULL);
70701  DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
70702 
70703  /* XXX: signalling the need to shrink check (only if unwound) */
70704 
70705  /* Must be restored here to handle e.g. yields properly. */
70706  heap->call_recursion_depth = entry_call_recursion_depth;
70707 
70708  /* Switch to caller's setjmp() catcher so that if an error occurs
70709  * during error handling, it is always propagated outwards instead
70710  * of causing an infinite loop in our own handler.
70711  */
70712  heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
70713 
70714  lj_ret = duk__handle_longjmp(heap->curr_thread, entry_thread, entry_callstack_top);
70715 
70716  if (lj_ret == DUK__LONGJMP_RESTART) {
70717  /* Restart bytecode execution, possibly with a changed thread. */
70718  ;
70719  } else {
70720  /* Rethrow error to calling state. */
70721  DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);
70722 
70723  /* Longjmp handling has restored jmpbuf_ptr. */
70724  DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);
70725 
70726  /* Thread may have changed, e.g. YIELD converted to THROW. */
70727  duk_err_longjmp(heap->curr_thread);
70728  DUK_UNREACHABLE();
70729  }
70730 }
70731 
70732 /* Outer executor with setjmp/longjmp handling. */
70733 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
70734  /* Entry level info. */
70735  duk_hthread *entry_thread;
70736  duk_size_t entry_callstack_top;
70737  duk_int_t entry_call_recursion_depth;
70738  duk_jmpbuf *entry_jmpbuf_ptr;
70739  duk_jmpbuf our_jmpbuf;
70740  duk_heap *heap;
70741 
70742  DUK_ASSERT(exec_thr != NULL);
70743  DUK_ASSERT(exec_thr->heap != NULL);
70744  DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
70745  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
70746  DUK_ASSERT(exec_thr->callstack_top >= 1); /* at least one activation, ours */
70747  DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1) != NULL);
70748  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack + exec_thr->callstack_top - 1)));
70749 
70750  entry_thread = exec_thr;
70751  heap = entry_thread->heap;
70752  entry_callstack_top = entry_thread->callstack_top;
70753  entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
70754  entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
70755 
70756  /*
70757  * Note: we currently assume that the setjmp() catchpoint is
70758  * not re-entrant (longjmp() cannot be called more than once
70759  * for a single setjmp()).
70760  *
70761  * See doc/code-issues.rst for notes on variable assignment
70762  * before and after setjmp().
70763  */
70764 
70765  for (;;) {
70766  heap->lj.jmpbuf_ptr = &our_jmpbuf;
70767  DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
70768 
70769 #if defined(DUK_USE_CPP_EXCEPTIONS)
70770  try {
70771 #else
70772  DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
70773  if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
70774 #endif
70775  /* Execute bytecode until returned or longjmp(). */
70776  duk__js_execute_bytecode_inner(entry_thread, entry_callstack_top);
70777 
70778  /* Successful return: restore jmpbuf and return to caller. */
70779  heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
70780 
70781  return;
70782 #if defined(DUK_USE_CPP_EXCEPTIONS)
70783  } catch (duk_internal_exception &exc) {
70784 #else
70785  } else {
70786 #endif
70787 #if defined(DUK_USE_CPP_EXCEPTIONS)
70788  DUK_UNREF(exc);
70789 #endif
70790  DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
70791 
70792  duk__handle_executor_error(heap,
70793  entry_thread,
70794  entry_callstack_top,
70795  entry_call_recursion_depth,
70796  entry_jmpbuf_ptr);
70797  }
70798 #if defined(DUK_USE_CPP_EXCEPTIONS)
70799  catch (std::exception &exc) {
70800  const char *what = exc.what();
70801  if (!what) {
70802  what = "unknown";
70803  }
70804  DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
70805  try {
70806  DUK_ASSERT(heap->curr_thread != NULL);
70807  DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
70808  } catch (duk_internal_exception exc) {
70809  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
70810  DUK_UNREF(exc);
70811  duk__handle_executor_error(heap,
70812  entry_thread,
70813  entry_callstack_top,
70814  entry_call_recursion_depth,
70815  entry_jmpbuf_ptr);
70816  }
70817  } catch (...) {
70818  DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
70819  try {
70820  DUK_ASSERT(heap->curr_thread != NULL);
70821  DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
70822  } catch (duk_internal_exception exc) {
70823  DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
70824  DUK_UNREF(exc);
70825  duk__handle_executor_error(heap,
70826  entry_thread,
70827  entry_callstack_top,
70828  entry_call_recursion_depth,
70829  entry_jmpbuf_ptr);
70830  }
70831  }
70832 #endif
70833  }
70834 
70835  DUK_UNREACHABLE();
70836 }
70837 
70838 /* Inner executor, performance critical. */
70839 DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_size_t entry_callstack_top) {
70840  /* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
70841  * Critical for performance. It would be safest to make this volatile,
70842  * but that eliminates performance benefits; aliasing guarantees
70843  * should be enough though.
70844  */
70845  duk_instr_t *curr_pc; /* bytecode has a stable pointer */
70846 
70847  /* Hot variables for interpretation. Critical for performance,
70848  * but must add sparingly to minimize register shuffling.
70849  */
70850  duk_hthread *thr; /* stable */
70851  duk_tval *consts; /* stable */
70852  duk_uint_fast32_t ins;
70853  /* 'funcs' is quite rarely used, so no local for it */
70854 #if defined(DUK_USE_EXEC_FUN_LOCAL)
70855  duk_hcompfunc *fun;
70856 #else
70857  /* 'fun' is quite rarely used, so no local for it */
70858 #endif
70859 
70860 #if defined(DUK_USE_INTERRUPT_COUNTER)
70861  duk_int_t int_ctr;
70862 #endif
70863 
70864 #if defined(DUK_USE_ASSERTIONS)
70865  duk_size_t valstack_top_base; /* valstack top, should match before interpreting each op (no leftovers) */
70866 #endif
70867 
70868  /* Optimized reg/const access macros assume sizeof(duk_tval) to be
70869  * either 8 or 16. Heap allocation checks this even without asserts
70870  * enabled now because it can't be autodetected in duk_config.h.
70871  */
70872 #if 1
70873 #if defined(DUK_USE_PACKED_TVAL)
70874  DUK_ASSERT(sizeof(duk_tval) == 8);
70875 #else
70876  DUK_ASSERT(sizeof(duk_tval) == 16);
70877 #endif
70878 #endif
70879 
70880  /*
70881  * Restart execution by reloading thread state.
70882  *
70883  * Note that 'thr' and any thread configuration may have changed,
70884  * so all local variables are suspect and we need to reinitialize.
70885  *
70886  * The number of local variables should be kept to a minimum: if
70887  * the variables are spilled, they will need to be loaded from
70888  * memory anyway.
70889  *
70890  * Any 'goto restart_execution;' code path in opcode dispatch must
70891  * ensure 'curr_pc' is synced back to act->curr_pc before the goto
70892  * takes place.
70893  *
70894  * The interpreter must be very careful with memory pointers, as
70895  * many pointers are not guaranteed to be 'stable' and may be
70896  * reallocated and relocated on-the-fly quite easily (e.g. by a
70897  * memory allocation or a property access).
70898  *
70899  * The following are assumed to have stable pointers:
70900  * - the current thread
70901  * - the current function
70902  * - the bytecode, constant table, inner function table of the
70903  * current function (as they are a part of the function allocation)
70904  *
70905  * The following are assumed to have semi-stable pointers:
70906  * - the current activation entry: stable as long as callstack
70907  * is not changed (reallocated by growing or shrinking), or
70908  * by any garbage collection invocation (through finalizers)
70909  * - Note in particular that ANY DECREF can invalidate the
70910  * activation pointer, so for the most part a fresh lookup
70911  * is required
70912  *
70913  * The following are not assumed to have stable pointers at all:
70914  * - the value stack (registers) of the current thread
70915  * - the catch stack of the current thread
70916  *
70917  * See execution.rst for discussion.
70918  */
70919 
70920  restart_execution:
70921 
70922  /* Lookup current thread; use the stable 'entry_thread' for this to
70923  * avoid clobber warnings. Any valid, reachable 'thr' value would be
70924  * fine for this, so using 'entry_thread' is just to silence warnings.
70925  */
70926  thr = entry_thread->heap->curr_thread;
70927  DUK_ASSERT(thr != NULL);
70928  DUK_ASSERT(thr->callstack_top >= 1);
70929  DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1) != NULL);
70930  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack + thr->callstack_top - 1)));
70931 
70932  thr->ptr_curr_pc = &curr_pc;
70933 
70934  /* Relookup and initialize dispatch loop variables. Debugger check. */
70935  {
70936  duk_activation *act;
70937 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
70938  duk_hcompfunc *fun;
70939 #endif
70940 
70941  /* Assume interrupt init/counter are properly initialized here. */
70942  /* Assume that thr->valstack_bottom has been set-up before getting here. */
70943 
70944  act = thr->callstack + thr->callstack_top - 1;
70945  fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
70946  DUK_ASSERT(fun != NULL);
70947  DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
70948  consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
70949  DUK_ASSERT(consts != NULL);
70950 
70951 #if defined(DUK_USE_DEBUGGER_SUPPORT)
70952  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap) && !thr->heap->dbg_processing) {
70953  duk__executor_recheck_debugger(thr, act, fun);
70954  act = thr->callstack + thr->callstack_top - 1; /* relookup after side effects (no side effects currently however) */
70955  }
70956 #endif /* DUK_USE_DEBUGGER_SUPPORT */
70957 
70958 #if defined(DUK_USE_ASSERTIONS)
70959  valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
70960 #endif
70961 
70962  /* Set up curr_pc for opcode dispatch. */
70963  curr_pc = act->curr_pc;
70964  }
70965 
70966  DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
70967  "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, catchstack_top=%ld, "
70968  "preventcount=%ld",
70969  (void *) thr,
70970  (long) (thr->callstack_top - 1),
70971  (void *) DUK__FUN(),
70972  (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
70973  (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
70974  (long) (thr->callstack_top - 1),
70975  (long) (thr->valstack_bottom - thr->valstack),
70976  (long) (thr->valstack_top - thr->valstack),
70977  (long) thr->catchstack_top,
70978  (long) thr->callstack_preventcount));
70979 
70980  /* Dispatch loop. */
70981 
70982  for (;;) {
70983  duk_uint8_t op;
70984 
70985  DUK_ASSERT(thr->callstack_top >= 1);
70986  DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
70987  DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
70988 
70989  /* Executor interrupt counter check, used to implement breakpoints,
70990  * debugging interface, execution timeouts, etc. The counter is heap
70991  * specific but is maintained in the current thread to make the check
70992  * as fast as possible. The counter is copied back to the heap struct
70993  * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
70994  */
70995 #if defined(DUK_USE_INTERRUPT_COUNTER)
70996  int_ctr = thr->interrupt_counter;
70997  if (DUK_LIKELY(int_ctr > 0)) {
70998  thr->interrupt_counter = int_ctr - 1;
70999  } else {
71000  /* Trigger at zero or below */
71001  duk_small_uint_t exec_int_ret;
71002 
71003  /* Write curr_pc back for the debugger. */
71004  DUK_ASSERT(thr->callstack_top > 0);
71005  {
71006  duk_activation *act;
71007  act = thr->callstack + thr->callstack_top - 1;
71008  act->curr_pc = (duk_instr_t *) curr_pc;
71009  }
71010 
71011  /* Force restart caused by a function return; must recheck
71012  * debugger breakpoints before checking line transitions,
71013  * see GH-303. Restart and then handle interrupt_counter
71014  * zero again.
71015  */
71016 #if defined(DUK_USE_DEBUGGER_SUPPORT)
71017  if (thr->heap->dbg_force_restart) {
71018  DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution")); /* GH-303 */
71019  thr->heap->dbg_force_restart = 0;
71020  goto restart_execution;
71021  }
71022 #endif
71023 
71024  exec_int_ret = duk__executor_interrupt(thr);
71025  if (exec_int_ret == DUK__INT_RESTART) {
71026  /* curr_pc synced back above */
71027  goto restart_execution;
71028  }
71029  }
71030 #endif /* DUK_USE_INTERRUPT_COUNTER */
71031 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
71032  /* For cross-checking during development: ensure dispatch count
71033  * matches cumulative interrupt counter init value sums.
71034  */
71035  thr->heap->inst_count_exec++;
71036 #endif
71037 
71038 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
71039  {
71040  duk_activation *act;
71041  act = thr->callstack + thr->callstack_top - 1;
71042  DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
71043  DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
71044  DUK_UNREF(act); /* if debugging disabled */
71045 
71046  DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld --> %!I",
71047  (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
71048  (unsigned long) *curr_pc,
71049  (long) DUK_DEC_OP(*curr_pc),
71050  (long) (thr->valstack_top - thr->valstack),
71051  (long) (thr->valstack_end - thr->valstack),
71052  (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
71053  (duk_instr_t) *curr_pc));
71054  }
71055 #endif
71056 
71057 #if defined(DUK_USE_ASSERTIONS)
71058  /* Quite heavy assert: check valstack policy. Improper
71059  * shuffle instructions can write beyond valstack_top/end
71060  * so this check catches them in the act.
71061  */
71062  {
71063  duk_tval *tv;
71064  tv = thr->valstack_top;
71065  while (tv != thr->valstack_end) {
71066  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
71067  tv++;
71068  }
71069  }
71070 #endif
71071 
71072  ins = *curr_pc++;
71073 
71074  /* Typing: use duk_small_(u)int_fast_t when decoding small
71075  * opcode fields (op, A, B, C, BC) which fit into 16 bits
71076  * and duk_(u)int_fast_t when decoding larger fields (e.g.
71077  * ABC). Use unsigned variant by default, signed when the
71078  * value is used in signed arithmetic. Using variable names
71079  * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
71080  * typing mismatches.
71081  */
71082 
71083  /* Switch based on opcode. Cast to 8-bit unsigned value and
71084  * use a fully populated case clauses so that the compiler
71085  * will (at least usually) omit a bounds check.
71086  */
71087  op = (duk_uint8_t) DUK_DEC_OP(ins);
71088  switch (op) {
71089 
71090  /* Some useful macros. These access inner executor variables
71091  * directly so they only apply within the executor.
71092  */
71093 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71094 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
71095 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
71096 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
71097  duk_bool_t duk__bval; \
71098  duk__bval = (bval); \
71099  DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
71100  duk_push_boolean((duk_context *) thr, duk__bval); \
71101  DUK__REPLACE_TOP_A_BREAK(); \
71102  }
71103 #else
71104 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
71105 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
71106 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
71107  duk_bool_t duk__bval; \
71108  duk_tval *duk__tvdst; \
71109  duk__bval = (bval); \
71110  DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
71111  duk__tvdst = DUK__REGP_A(ins); \
71112  DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
71113  break; \
71114  }
71115 #endif
71116 
71117  /* XXX: 12 + 12 bit variant might make sense too, for both reg and
71118  * const loads.
71119  */
71120 
71121  /* For LDREG, STREG, LDCONST footprint optimized variants would just
71122  * duk_dup() + duk_replace(), but because they're used quite a lot
71123  * they're currently intentionally not size optimized.
71124  */
71125  case DUK_OP_LDREG: {
71126  duk_tval *tv1, *tv2;
71127 
71128  tv1 = DUK__REGP_A(ins);
71129  tv2 = DUK__REGP_BC(ins);
71130  DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
71131  break;
71132  }
71133 
71134  case DUK_OP_STREG: {
71135  duk_tval *tv1, *tv2;
71136 
71137  tv1 = DUK__REGP_A(ins);
71138  tv2 = DUK__REGP_BC(ins);
71139  DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1); /* side effects */
71140  break;
71141  }
71142 
71143  case DUK_OP_LDCONST: {
71144  duk_tval *tv1, *tv2;
71145 
71146  tv1 = DUK__REGP_A(ins);
71147  tv2 = DUK__CONSTP_BC(ins);
71148  DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
71149  break;
71150  }
71151 
71152  /* LDINT and LDINTX are intended to load an arbitrary signed
71153  * 32-bit value. Only an LDINT+LDINTX sequence is supported.
71154  * This also guarantees all values remain fastints.
71155  */
71156 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71157  case DUK_OP_LDINT: {
71158  duk_int32_t val;
71159 
71160  val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
71161  duk_push_int((duk_context *) thr, val);
71162  DUK__REPLACE_TOP_A_BREAK();
71163  }
71164  case DUK_OP_LDINTX: {
71165  duk_int32_t val;
71166 
71167  val = (duk_int32_t) duk_get_int((duk_context *) thr, DUK_DEC_A(ins));
71168  val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
71169  duk_push_int((duk_context *) thr, val);
71170  DUK__REPLACE_TOP_A_BREAK();
71171  }
71172 #else /* DUK_USE_EXEC_PREFER_SIZE */
71173  case DUK_OP_LDINT: {
71174  duk_tval *tv1;
71175  duk_int32_t val;
71176 
71177  val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
71178  tv1 = DUK__REGP_A(ins);
71179  DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
71180  break;
71181  }
71182  case DUK_OP_LDINTX: {
71183  duk_tval *tv1;
71184  duk_int32_t val;
71185 
71186  tv1 = DUK__REGP_A(ins);
71187  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
71188 #if defined(DUK_USE_FASTINT)
71189  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
71190  val = DUK_TVAL_GET_FASTINT_I32(tv1);
71191 #else
71192  /* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
71193  val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
71194 #endif
71195  val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins); /* no bias */
71196  DUK_TVAL_SET_I32_UPDREF(thr, tv1, val); /* side effects */
71197  break;
71198  }
71199 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71200 
71201 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71202  case DUK_OP_LDTHIS: {
71203  duk_push_this((duk_context *) thr);
71204  DUK__REPLACE_TOP_BC_BREAK();
71205  }
71206  case DUK_OP_LDUNDEF: {
71207  duk_to_undefined((duk_context *) thr, (duk_idx_t) DUK_DEC_BC(ins));
71208  break;
71209  }
71210  case DUK_OP_LDNULL: {
71211  duk_to_null((duk_context *) thr, (duk_idx_t) DUK_DEC_BC(ins));
71212  break;
71213  }
71214  case DUK_OP_LDTRUE: {
71215  duk_push_true((duk_context *) thr);
71216  DUK__REPLACE_TOP_BC_BREAK();
71217  }
71218  case DUK_OP_LDFALSE: {
71219  duk_push_false((duk_context *) thr);
71220  DUK__REPLACE_TOP_BC_BREAK();
71221  }
71222 #else /* DUK_USE_EXEC_PREFER_SIZE */
71223  case DUK_OP_LDTHIS: {
71224  /* Note: 'this' may be bound to any value, not just an object */
71225  duk_tval *tv1, *tv2;
71226 
71227  tv1 = DUK__REGP_BC(ins);
71228  tv2 = thr->valstack_bottom - 1; /* 'this binding' is just under bottom */
71229  DUK_ASSERT(tv2 >= thr->valstack);
71230  DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2); /* side effects */
71231  break;
71232  }
71233  case DUK_OP_LDUNDEF: {
71234  duk_tval *tv1;
71235 
71236  tv1 = DUK__REGP_BC(ins);
71237  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
71238  break;
71239  }
71240  case DUK_OP_LDNULL: {
71241  duk_tval *tv1;
71242 
71243  tv1 = DUK__REGP_BC(ins);
71244  DUK_TVAL_SET_NULL_UPDREF(thr, tv1); /* side effects */
71245  break;
71246  }
71247  case DUK_OP_LDTRUE: {
71248  duk_tval *tv1;
71249 
71250  tv1 = DUK__REGP_BC(ins);
71251  DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1); /* side effects */
71252  break;
71253  }
71254  case DUK_OP_LDFALSE: {
71255  duk_tval *tv1;
71256 
71257  tv1 = DUK__REGP_BC(ins);
71258  DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0); /* side effects */
71259  break;
71260  }
71261 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71262 
71263  case DUK_OP_BNOT: {
71264  duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
71265  break;
71266  }
71267 
71268  case DUK_OP_LNOT: {
71269  duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
71270  break;
71271  }
71272 
71273 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71274  case DUK_OP_UNM:
71275  case DUK_OP_UNP: {
71276  duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
71277  break;
71278  }
71279 #else /* DUK_USE_EXEC_PREFER_SIZE */
71280  case DUK_OP_UNM: {
71281  duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
71282  break;
71283  }
71284  case DUK_OP_UNP: {
71285  duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
71286  break;
71287  }
71288 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71289 
71290 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71291  case DUK_OP_TYPEOF: {
71292  duk_small_uint_t stridx;
71293 
71294  stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
71295  DUK_ASSERT(stridx >= 0 && stridx < DUK_HEAP_NUM_STRINGS);
71296  duk_push_hstring_stridx((duk_context *) thr, stridx);
71297  DUK__REPLACE_TOP_A_BREAK();
71298  }
71299 #else /* DUK_USE_EXEC_PREFER_SIZE */
71300  case DUK_OP_TYPEOF: {
71301  duk_tval *tv;
71302  duk_small_uint_t stridx;
71303  duk_hstring *h_str;
71304 
71305  tv = DUK__REGP_BC(ins);
71306  stridx = duk_js_typeof_stridx(tv);
71307  DUK_ASSERT_STRIDX_VALID(stridx);
71308  h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
71309  tv = DUK__REGP_A(ins);
71310  DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
71311  break;
71312  }
71313 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71314 
71315  case DUK_OP_TYPEOFID: {
71316  duk_context *ctx = (duk_context *) thr;
71317  duk_small_uint_t stridx;
71318 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
71319  duk_hstring *h_str;
71320 #endif
71321  duk_activation *act;
71322  duk_hstring *name;
71323  duk_tval *tv;
71324 
71325  /* A -> target register
71326  * BC -> constant index of identifier name
71327  */
71328 
71329  tv = DUK__CONSTP_BC(ins);
71330  DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
71331  name = DUK_TVAL_GET_STRING(tv);
71332  tv = NULL; /* lookup has side effects */
71333  act = thr->callstack + thr->callstack_top - 1;
71334  if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
71335  /* -> [... val this] */
71336  tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
71337  stridx = duk_js_typeof_stridx(tv);
71338  tv = NULL; /* no longer needed */
71339  duk_pop_2(ctx);
71340  } else {
71341  /* unresolvable, no stack changes */
71342  stridx = DUK_STRIDX_LC_UNDEFINED;
71343  }
71344  DUK_ASSERT_STRIDX_VALID(stridx);
71345 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71346  duk_push_hstring_stridx(ctx, stridx);
71347  DUK__REPLACE_TOP_A_BREAK();
71348 #else /* DUK_USE_EXEC_PREFER_SIZE */
71349  h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
71350  tv = DUK__REGP_A(ins);
71351  DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
71352  break;
71353 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71354  }
71355 
71356  /* Equality: E5 Sections 11.9.1, 11.9.3 */
71357 
71358 #define DUK__EQ_BODY(barg,carg) { \
71359  duk_bool_t tmp; \
71360  tmp = duk_js_equals(thr, (barg), (carg)); \
71361  DUK_ASSERT(tmp == 0 || tmp == 1); \
71362  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71363  }
71364 #define DUK__NEQ_BODY(barg,carg) { \
71365  duk_bool_t tmp; \
71366  tmp = duk_js_equals(thr, (barg), (carg)); \
71367  DUK_ASSERT(tmp == 0 || tmp == 1); \
71368  tmp ^= 1; \
71369  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71370  }
71371 #define DUK__SEQ_BODY(barg,carg) { \
71372  duk_bool_t tmp; \
71373  tmp = duk_js_strict_equals((barg), (carg)); \
71374  DUK_ASSERT(tmp == 0 || tmp == 1); \
71375  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71376  }
71377 #define DUK__SNEQ_BODY(barg,carg) { \
71378  duk_bool_t tmp; \
71379  tmp = duk_js_strict_equals((barg), (carg)); \
71380  DUK_ASSERT(tmp == 0 || tmp == 1); \
71381  tmp ^= 1; \
71382  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71383  }
71384 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71385  case DUK_OP_EQ_RR:
71386  case DUK_OP_EQ_CR:
71387  case DUK_OP_EQ_RC:
71388  case DUK_OP_EQ_CC:
71389  DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71390  case DUK_OP_NEQ_RR:
71391  case DUK_OP_NEQ_CR:
71392  case DUK_OP_NEQ_RC:
71393  case DUK_OP_NEQ_CC:
71394  DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71395  case DUK_OP_SEQ_RR:
71396  case DUK_OP_SEQ_CR:
71397  case DUK_OP_SEQ_RC:
71398  case DUK_OP_SEQ_CC:
71399  DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71400  case DUK_OP_SNEQ_RR:
71401  case DUK_OP_SNEQ_CR:
71402  case DUK_OP_SNEQ_RC:
71403  case DUK_OP_SNEQ_CC:
71404  DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71405 #else /* DUK_USE_EXEC_PREFER_SIZE */
71406  case DUK_OP_EQ_RR:
71407  DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71408  case DUK_OP_EQ_CR:
71409  DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71410  case DUK_OP_EQ_RC:
71411  DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71412  case DUK_OP_EQ_CC:
71413  DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71414  case DUK_OP_NEQ_RR:
71415  DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71416  case DUK_OP_NEQ_CR:
71417  DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71418  case DUK_OP_NEQ_RC:
71419  DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71420  case DUK_OP_NEQ_CC:
71421  DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71422  case DUK_OP_SEQ_RR:
71423  DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71424  case DUK_OP_SEQ_CR:
71425  DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71426  case DUK_OP_SEQ_RC:
71427  DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71428  case DUK_OP_SEQ_CC:
71429  DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71430  case DUK_OP_SNEQ_RR:
71431  DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71432  case DUK_OP_SNEQ_CR:
71433  DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71434  case DUK_OP_SNEQ_RC:
71435  DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71436  case DUK_OP_SNEQ_CC:
71437  DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71438 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71439 
71440 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
71441  duk_bool_t tmp; \
71442  tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
71443  DUK_ASSERT(tmp == 0 || tmp == 1); \
71444  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71445  }
71446 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
71447 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
71448 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
71449 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
71450 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71451  case DUK_OP_GT_RR:
71452  case DUK_OP_GT_CR:
71453  case DUK_OP_GT_RC:
71454  case DUK_OP_GT_CC:
71455  DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71456  case DUK_OP_GE_RR:
71457  case DUK_OP_GE_CR:
71458  case DUK_OP_GE_RC:
71459  case DUK_OP_GE_CC:
71460  DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71461  case DUK_OP_LT_RR:
71462  case DUK_OP_LT_CR:
71463  case DUK_OP_LT_RC:
71464  case DUK_OP_LT_CC:
71465  DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71466  case DUK_OP_LE_RR:
71467  case DUK_OP_LE_CR:
71468  case DUK_OP_LE_RC:
71469  case DUK_OP_LE_CC:
71470  DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71471 #else /* DUK_USE_EXEC_PREFER_SIZE */
71472  case DUK_OP_GT_RR:
71473  DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71474  case DUK_OP_GT_CR:
71475  DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71476  case DUK_OP_GT_RC:
71477  DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71478  case DUK_OP_GT_CC:
71479  DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71480  case DUK_OP_GE_RR:
71481  DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71482  case DUK_OP_GE_CR:
71483  DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71484  case DUK_OP_GE_RC:
71485  DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71486  case DUK_OP_GE_CC:
71487  DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71488  case DUK_OP_LT_RR:
71489  DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71490  case DUK_OP_LT_CR:
71491  DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71492  case DUK_OP_LT_RC:
71493  DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71494  case DUK_OP_LT_CC:
71495  DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71496  case DUK_OP_LE_RR:
71497  DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71498  case DUK_OP_LE_CR:
71499  DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71500  case DUK_OP_LE_RC:
71501  DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71502  case DUK_OP_LE_CC:
71503  DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71504 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71505 
71506  /* No size optimized variant at present for IF. */
71507  case DUK_OP_IFTRUE_R: {
71508  if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
71509  curr_pc++;
71510  }
71511  break;
71512  }
71513  case DUK_OP_IFTRUE_C: {
71514  if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
71515  curr_pc++;
71516  }
71517  break;
71518  }
71519  case DUK_OP_IFFALSE_R: {
71520  if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
71521  curr_pc++;
71522  }
71523  break;
71524  }
71525  case DUK_OP_IFFALSE_C: {
71526  if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
71527  curr_pc++;
71528  }
71529  break;
71530  }
71531 
71532 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71533  case DUK_OP_ADD_RR:
71534  case DUK_OP_ADD_CR:
71535  case DUK_OP_ADD_RC:
71536  case DUK_OP_ADD_CC: {
71537  /* XXX: could leave value on stack top and goto replace_top_a; */
71538  duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
71539  break;
71540  }
71541 #else /* DUK_USE_EXEC_PREFER_SIZE */
71542  case DUK_OP_ADD_RR: {
71543  duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
71544  break;
71545  }
71546  case DUK_OP_ADD_CR: {
71547  duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
71548  break;
71549  }
71550  case DUK_OP_ADD_RC: {
71551  duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
71552  break;
71553  }
71554  case DUK_OP_ADD_CC: {
71555  duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
71556  break;
71557  }
71558 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71559 
71560 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71561  case DUK_OP_SUB_RR:
71562  case DUK_OP_SUB_CR:
71563  case DUK_OP_SUB_RC:
71564  case DUK_OP_SUB_CC:
71565  case DUK_OP_MUL_RR:
71566  case DUK_OP_MUL_CR:
71567  case DUK_OP_MUL_RC:
71568  case DUK_OP_MUL_CC:
71569  case DUK_OP_DIV_RR:
71570  case DUK_OP_DIV_CR:
71571  case DUK_OP_DIV_RC:
71572  case DUK_OP_DIV_CC:
71573  case DUK_OP_MOD_RR:
71574  case DUK_OP_MOD_CR:
71575  case DUK_OP_MOD_RC:
71576  case DUK_OP_MOD_CC:
71577 #if defined(DUK_USE_ES7_EXP_OPERATOR)
71578  case DUK_OP_EXP_RR:
71579  case DUK_OP_EXP_CR:
71580  case DUK_OP_EXP_RC:
71581  case DUK_OP_EXP_CC:
71582 #endif /* DUK_USE_ES7_EXP_OPERATOR */
71583  {
71584  /* XXX: could leave value on stack top and goto replace_top_a; */
71585  duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
71586  break;
71587  }
71588 #else /* DUK_USE_EXEC_PREFER_SIZE */
71589  case DUK_OP_SUB_RR: {
71590  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
71591  break;
71592  }
71593  case DUK_OP_SUB_CR: {
71594  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
71595  break;
71596  }
71597  case DUK_OP_SUB_RC: {
71598  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
71599  break;
71600  }
71601  case DUK_OP_SUB_CC: {
71602  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
71603  break;
71604  }
71605  case DUK_OP_MUL_RR: {
71606  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
71607  break;
71608  }
71609  case DUK_OP_MUL_CR: {
71610  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
71611  break;
71612  }
71613  case DUK_OP_MUL_RC: {
71614  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
71615  break;
71616  }
71617  case DUK_OP_MUL_CC: {
71618  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
71619  break;
71620  }
71621  case DUK_OP_DIV_RR: {
71622  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
71623  break;
71624  }
71625  case DUK_OP_DIV_CR: {
71626  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
71627  break;
71628  }
71629  case DUK_OP_DIV_RC: {
71630  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
71631  break;
71632  }
71633  case DUK_OP_DIV_CC: {
71634  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
71635  break;
71636  }
71637  case DUK_OP_MOD_RR: {
71638  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
71639  break;
71640  }
71641  case DUK_OP_MOD_CR: {
71642  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
71643  break;
71644  }
71645  case DUK_OP_MOD_RC: {
71646  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
71647  break;
71648  }
71649  case DUK_OP_MOD_CC: {
71650  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
71651  break;
71652  }
71653 #if defined(DUK_USE_ES7_EXP_OPERATOR)
71654  case DUK_OP_EXP_RR: {
71655  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
71656  break;
71657  }
71658  case DUK_OP_EXP_CR: {
71659  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
71660  break;
71661  }
71662  case DUK_OP_EXP_RC: {
71663  duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
71664  break;
71665  }
71666  case DUK_OP_EXP_CC: {
71667  duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
71668  break;
71669  }
71670 #endif /* DUK_USE_ES7_EXP_OPERATOR */
71671 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71672 
71673 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71674  case DUK_OP_BAND_RR:
71675  case DUK_OP_BAND_CR:
71676  case DUK_OP_BAND_RC:
71677  case DUK_OP_BAND_CC:
71678  case DUK_OP_BOR_RR:
71679  case DUK_OP_BOR_CR:
71680  case DUK_OP_BOR_RC:
71681  case DUK_OP_BOR_CC:
71682  case DUK_OP_BXOR_RR:
71683  case DUK_OP_BXOR_CR:
71684  case DUK_OP_BXOR_RC:
71685  case DUK_OP_BXOR_CC:
71686  case DUK_OP_BASL_RR:
71687  case DUK_OP_BASL_CR:
71688  case DUK_OP_BASL_RC:
71689  case DUK_OP_BASL_CC:
71690  case DUK_OP_BLSR_RR:
71691  case DUK_OP_BLSR_CR:
71692  case DUK_OP_BLSR_RC:
71693  case DUK_OP_BLSR_CC:
71694  case DUK_OP_BASR_RR:
71695  case DUK_OP_BASR_CR:
71696  case DUK_OP_BASR_RC:
71697  case DUK_OP_BASR_CC: {
71698  /* XXX: could leave value on stack top and goto replace_top_a; */
71699  duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
71700  break;
71701  }
71702 #else /* DUK_USE_EXEC_PREFER_SIZE */
71703  case DUK_OP_BAND_RR: {
71704  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
71705  break;
71706  }
71707  case DUK_OP_BAND_CR: {
71708  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
71709  break;
71710  }
71711  case DUK_OP_BAND_RC: {
71712  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
71713  break;
71714  }
71715  case DUK_OP_BAND_CC: {
71716  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
71717  break;
71718  }
71719  case DUK_OP_BOR_RR: {
71720  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
71721  break;
71722  }
71723  case DUK_OP_BOR_CR: {
71724  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
71725  break;
71726  }
71727  case DUK_OP_BOR_RC: {
71728  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
71729  break;
71730  }
71731  case DUK_OP_BOR_CC: {
71732  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
71733  break;
71734  }
71735  case DUK_OP_BXOR_RR: {
71736  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
71737  break;
71738  }
71739  case DUK_OP_BXOR_CR: {
71740  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
71741  break;
71742  }
71743  case DUK_OP_BXOR_RC: {
71744  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
71745  break;
71746  }
71747  case DUK_OP_BXOR_CC: {
71748  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
71749  break;
71750  }
71751  case DUK_OP_BASL_RR: {
71752  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
71753  break;
71754  }
71755  case DUK_OP_BASL_CR: {
71756  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
71757  break;
71758  }
71759  case DUK_OP_BASL_RC: {
71760  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
71761  break;
71762  }
71763  case DUK_OP_BASL_CC: {
71764  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
71765  break;
71766  }
71767  case DUK_OP_BLSR_RR: {
71768  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
71769  break;
71770  }
71771  case DUK_OP_BLSR_CR: {
71772  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
71773  break;
71774  }
71775  case DUK_OP_BLSR_RC: {
71776  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
71777  break;
71778  }
71779  case DUK_OP_BLSR_CC: {
71780  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
71781  break;
71782  }
71783  case DUK_OP_BASR_RR: {
71784  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
71785  break;
71786  }
71787  case DUK_OP_BASR_CR: {
71788  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
71789  break;
71790  }
71791  case DUK_OP_BASR_RC: {
71792  duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
71793  break;
71794  }
71795  case DUK_OP_BASR_CC: {
71796  duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
71797  break;
71798  }
71799 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71800 
71801  /* For INSTOF and IN, B is always a register. */
71802 #define DUK__INSTOF_BODY(barg,carg) { \
71803  duk_bool_t tmp; \
71804  tmp = duk_js_instanceof(thr, (barg), (carg)); \
71805  DUK_ASSERT(tmp == 0 || tmp == 1); \
71806  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71807  }
71808 #define DUK__IN_BODY(barg,carg) { \
71809  duk_bool_t tmp; \
71810  tmp = duk_js_in(thr, (barg), (carg)); \
71811  DUK_ASSERT(tmp == 0 || tmp == 1); \
71812  DUK__REPLACE_BOOL_A_BREAK(tmp); \
71813  }
71814 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71815  case DUK_OP_INSTOF_RR:
71816  case DUK_OP_INSTOF_CR:
71817  case DUK_OP_INSTOF_RC:
71818  case DUK_OP_INSTOF_CC:
71819  DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71820  case DUK_OP_IN_RR:
71821  case DUK_OP_IN_CR:
71822  case DUK_OP_IN_RC:
71823  case DUK_OP_IN_CC:
71824  DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
71825 #else /* DUK_USE_EXEC_PREFER_SIZE */
71826  case DUK_OP_INSTOF_RR:
71827  DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71828  case DUK_OP_INSTOF_CR:
71829  DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71830  case DUK_OP_INSTOF_RC:
71831  DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71832  case DUK_OP_INSTOF_CC:
71833  DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71834  case DUK_OP_IN_RR:
71835  DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
71836  case DUK_OP_IN_CR:
71837  DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
71838  case DUK_OP_IN_RC:
71839  DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
71840  case DUK_OP_IN_CC:
71841  DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
71842 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71843 
71844  /* Pre/post inc/dec for register variables, important for loops. */
71845 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71846  case DUK_OP_PREINCR:
71847  case DUK_OP_PREDECR:
71848  case DUK_OP_POSTINCR:
71849  case DUK_OP_POSTDECR: {
71850  duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
71851  break;
71852  }
71853  case DUK_OP_PREINCV:
71854  case DUK_OP_PREDECV:
71855  case DUK_OP_POSTINCV:
71856  case DUK_OP_POSTDECV: {
71857  duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
71858  break;
71859  }
71860 #else /* DUK_USE_EXEC_PREFER_SIZE */
71861  case DUK_OP_PREINCR: {
71862  duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
71863  break;
71864  }
71865  case DUK_OP_PREDECR: {
71866  duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
71867  break;
71868  }
71869  case DUK_OP_POSTINCR: {
71870  duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
71871  break;
71872  }
71873  case DUK_OP_POSTDECR: {
71874  duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
71875  break;
71876  }
71877  case DUK_OP_PREINCV: {
71878  duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
71879  break;
71880  }
71881  case DUK_OP_PREDECV: {
71882  duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
71883  break;
71884  }
71885  case DUK_OP_POSTINCV: {
71886  duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
71887  break;
71888  }
71889  case DUK_OP_POSTDECV: {
71890  duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
71891  break;
71892  }
71893 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71894 
71895  /* XXX: Move to separate helper, optimize for perf/size separately. */
71896  /* Preinc/predec for object properties. */
71897  case DUK_OP_PREINCP_RR:
71898  case DUK_OP_PREINCP_CR:
71899  case DUK_OP_PREINCP_RC:
71900  case DUK_OP_PREINCP_CC:
71901  case DUK_OP_PREDECP_RR:
71902  case DUK_OP_PREDECP_CR:
71903  case DUK_OP_PREDECP_RC:
71904  case DUK_OP_PREDECP_CC:
71905  case DUK_OP_POSTINCP_RR:
71906  case DUK_OP_POSTINCP_CR:
71907  case DUK_OP_POSTINCP_RC:
71908  case DUK_OP_POSTINCP_CC:
71909  case DUK_OP_POSTDECP_RR:
71910  case DUK_OP_POSTDECP_CR:
71911  case DUK_OP_POSTDECP_RC:
71912  case DUK_OP_POSTDECP_CC: {
71913  duk_context *ctx = (duk_context *) thr;
71914  duk_tval *tv_obj;
71915  duk_tval *tv_key;
71916  duk_tval *tv_val;
71917  duk_bool_t rc;
71918  duk_double_t x, y, z;
71919 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
71920  duk_tval *tv_dst;
71921 #endif /* DUK_USE_EXEC_PREFER_SIZE */
71922 
71923  /* A -> target reg
71924  * B -> object reg/const (may be const e.g. in "'foo'[1]")
71925  * C -> key reg/const
71926  */
71927 
71928  /* Opcode bits 0-1 are used to distinguish reg/const variants.
71929  * Opcode bits 2-3 are used to distinguish inc/dec variants:
71930  * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
71931  */
71932  DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
71933  DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
71934  DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
71935  DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
71936 
71937  tv_obj = DUK__REGCONSTP_B(ins);
71938  tv_key = DUK__REGCONSTP_C(ins);
71939  rc = duk_hobject_getprop(thr, tv_obj, tv_key); /* -> [val] */
71940  DUK_UNREF(rc); /* ignore */
71941  tv_obj = NULL; /* invalidated */
71942  tv_key = NULL; /* invalidated */
71943 
71944  /* XXX: Fastint fast path would be useful here. Also fastints
71945  * now lose their fastint status in current handling which is
71946  * not intuitive.
71947  */
71948 
71949  x = duk_to_number_m1(ctx);
71950  duk_pop(ctx);
71951  if (ins & DUK_BC_INCDECP_FLAG_DEC) {
71952  y = x - 1.0;
71953  } else {
71954  y = x + 1.0;
71955  }
71956 
71957  duk_push_number(ctx, y);
71958  tv_val = DUK_GET_TVAL_NEGIDX(ctx, -1);
71959  DUK_ASSERT(tv_val != NULL);
71960  tv_obj = DUK__REGCONSTP_B(ins);
71961  tv_key = DUK__REGCONSTP_C(ins);
71962  rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
71963  DUK_UNREF(rc); /* ignore */
71964  tv_obj = NULL; /* invalidated */
71965  tv_key = NULL; /* invalidated */
71966  duk_pop(ctx);
71967 
71968  z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
71969 #if defined(DUK_USE_EXEC_PREFER_SIZE)
71970  duk_push_number(ctx, z);
71971  DUK__REPLACE_TOP_A_BREAK();
71972 #else
71973  tv_dst = DUK__REGP_A(ins);
71974  DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
71975  break;
71976 #endif
71977  }
71978 
71979  /* XXX: GETPROP where object is 'this', GETPROPT?
71980  * Occurs relatively often in object oriented code.
71981  */
71982 
71983 #define DUK__GETPROP_BODY(barg,carg) { \
71984  /* A -> target reg \
71985  * B -> object reg/const (may be const e.g. in "'foo'[1]") \
71986  * C -> key reg/const \
71987  */ \
71988  (void) duk_hobject_getprop(thr, (barg), (carg)); \
71989  DUK__REPLACE_TOP_A_BREAK(); \
71990  }
71991 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
71992  /* A -> object reg \
71993  * B -> key reg/const \
71994  * C -> value reg/const \
71995  * \
71996  * Note: intentional difference to register arrangement \
71997  * of e.g. GETPROP; 'A' must contain a register-only value. \
71998  */ \
71999  (void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
72000  break; \
72001  }
72002 #define DUK__DELPROP_BODY(barg,carg) { \
72003  /* A -> result reg \
72004  * B -> object reg \
72005  * C -> key reg/const \
72006  */ \
72007  duk_bool_t rc; \
72008  rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
72009  DUK_ASSERT(rc == 0 || rc == 1); \
72010  DUK__REPLACE_BOOL_A_BREAK(rc); \
72011  }
72012 #if defined(DUK_USE_EXEC_PREFER_SIZE)
72013  case DUK_OP_GETPROP_RR:
72014  case DUK_OP_GETPROP_CR:
72015  case DUK_OP_GETPROP_RC:
72016  case DUK_OP_GETPROP_CC:
72017  DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
72018  case DUK_OP_PUTPROP_RR:
72019  case DUK_OP_PUTPROP_CR:
72020  case DUK_OP_PUTPROP_RC:
72021  case DUK_OP_PUTPROP_CC:
72022  DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
72023  case DUK_OP_DELPROP_RR:
72024  case DUK_OP_DELPROP_RC: /* B is always reg */
72025  DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
72026 #else /* DUK_USE_EXEC_PREFER_SIZE */
72027  case DUK_OP_GETPROP_RR:
72028  DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
72029  case DUK_OP_GETPROP_CR:
72030  DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
72031  case DUK_OP_GETPROP_RC:
72032  DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
72033  case DUK_OP_GETPROP_CC:
72034  DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
72035  case DUK_OP_PUTPROP_RR:
72036  DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
72037  case DUK_OP_PUTPROP_CR:
72038  DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
72039  case DUK_OP_PUTPROP_RC:
72040  DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
72041  case DUK_OP_PUTPROP_CC:
72042  DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
72043  case DUK_OP_DELPROP_RR: /* B is always reg */
72044  DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
72045  case DUK_OP_DELPROP_RC:
72046  DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
72047 #endif /* DUK_USE_EXEC_PREFER_SIZE */
72048 
72049  /* No fast path for DECLVAR now, it's quite a rare instruction. */
72050  case DUK_OP_DECLVAR_RR:
72051  case DUK_OP_DECLVAR_CR:
72052  case DUK_OP_DECLVAR_RC:
72053  case DUK_OP_DECLVAR_CC: {
72054  duk_activation *act;
72055  duk_context *ctx = (duk_context *) thr;
72056  duk_small_uint_fast_t a = DUK_DEC_A(ins);
72057  duk_tval *tv1;
72058  duk_hstring *name;
72059  duk_small_uint_t prop_flags;
72060  duk_bool_t is_func_decl;
72061  duk_bool_t is_undef_value;
72062 
72063  tv1 = DUK__REGCONSTP_B(ins);
72064  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72065  name = DUK_TVAL_GET_STRING(tv1);
72066  DUK_ASSERT(name != NULL);
72067 
72068  is_undef_value = ((a & DUK_BC_DECLVAR_FLAG_UNDEF_VALUE) != 0);
72069  is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
72070 
72071  /* XXX: declvar takes an duk_tval pointer, which is awkward and
72072  * should be reworked.
72073  */
72074 
72075  /* Compiler is responsible for selecting property flags (configurability,
72076  * writability, etc).
72077  */
72078  prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
72079 
72080  if (is_undef_value) {
72081  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
72082  thr->valstack_top++;
72083  } else {
72084  duk_push_tval(ctx, DUK__REGCONSTP_C(ins));
72085  }
72086  tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
72087 
72088  act = thr->callstack + thr->callstack_top - 1;
72089  if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
72090  /* already declared, must update binding value */
72091  tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
72092  duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
72093  }
72094 
72095  duk_pop(ctx);
72096  break;
72097  }
72098 
72099 #if defined(DUK_USE_REGEXP_SUPPORT)
72100  /* The compiler should never emit DUK_OP_REGEXP if there is no
72101  * regexp support.
72102  */
72103  case DUK_OP_REGEXP_RR:
72104  case DUK_OP_REGEXP_CR:
72105  case DUK_OP_REGEXP_RC:
72106  case DUK_OP_REGEXP_CC: {
72107  /* A -> target register
72108  * B -> bytecode (also contains flags)
72109  * C -> escaped source
72110  */
72111 
72112  duk_push_tval((duk_context *) thr, DUK__REGCONSTP_C(ins));
72113  duk_push_tval((duk_context *) thr, DUK__REGCONSTP_B(ins)); /* -> [ ... escaped_source bytecode ] */
72114  duk_regexp_create_instance(thr); /* -> [ ... regexp_instance ] */
72115  DUK__REPLACE_TOP_A_BREAK();
72116  }
72117 #endif /* DUK_USE_REGEXP_SUPPORT */
72118 
72119  /* XXX: 'c' is unused, use whole BC, etc. */
72120  case DUK_OP_CSVAR_RR:
72121  case DUK_OP_CSVAR_CR:
72122  case DUK_OP_CSVAR_RC:
72123  case DUK_OP_CSVAR_CC: {
72124  /* The speciality of calling through a variable binding is that the
72125  * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
72126  *
72127  * The only (standard) case where the 'this' binding is non-null is when
72128  * (1) the variable is found in an object environment record, and
72129  * (2) that object environment record is a 'with' block.
72130  */
72131 
72132  duk_context *ctx = (duk_context *) thr;
72133  duk_activation *act;
72134  duk_uint_fast_t idx;
72135  duk_tval *tv1;
72136  duk_hstring *name;
72137 
72138  /* A -> target registers (A, A + 1) for call setup
72139  * B -> identifier name, usually constant but can be a register due to shuffling
72140  */
72141 
72142  tv1 = DUK__REGCONSTP_B(ins);
72143  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72144  name = DUK_TVAL_GET_STRING(tv1);
72145  DUK_ASSERT(name != NULL);
72146  act = thr->callstack + thr->callstack_top - 1;
72147  (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
72148 
72149  idx = (duk_uint_fast_t) DUK_DEC_A(ins);
72150 
72151  /* Could add direct value stack handling. */
72152  duk_replace(ctx, (duk_idx_t) (idx + 1)); /* 'this' binding */
72153  duk_replace(ctx, (duk_idx_t) idx); /* variable value (function, we hope, not checked here) */
72154  break;
72155  }
72156 
72157  case DUK_OP_CLOSURE: {
72158  duk_activation *act;
72159  duk_hcompfunc *fun_act;
72160  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72161  duk_hobject *fun_temp;
72162 
72163  /* A -> target reg
72164  * BC -> inner function index
72165  */
72166 
72167  DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
72168  (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
72169 
72170  DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
72171  DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
72172 
72173  act = thr->callstack + thr->callstack_top - 1;
72174  fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
72175  fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
72176  DUK_ASSERT(fun_temp != NULL);
72177  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
72178 
72179  DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
72180  (void *) fun_temp, (duk_heaphdr *) fun_temp));
72181 
72182  if (act->lex_env == NULL) {
72183  DUK_ASSERT(act->var_env == NULL);
72184  duk_js_init_activation_environment_records_delayed(thr, act);
72185  }
72186  DUK_ASSERT(act->lex_env != NULL);
72187  DUK_ASSERT(act->var_env != NULL);
72188 
72189  /* functions always have a NEWENV flag, i.e. they get a
72190  * new variable declaration environment, so only lex_env
72191  * matters here.
72192  */
72193  duk_js_push_closure(thr,
72194  (duk_hcompfunc *) fun_temp,
72195  act->var_env,
72196  act->lex_env,
72197  1 /*add_auto_proto*/);
72198  DUK__REPLACE_TOP_A_BREAK();
72199  }
72200 
72201  case DUK_OP_GETVAR: {
72202  duk_context *ctx = (duk_context *) thr;
72203  duk_activation *act;
72204  duk_tval *tv1;
72205  duk_hstring *name;
72206 
72207  tv1 = DUK__CONSTP_BC(ins);
72208  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72209  name = DUK_TVAL_GET_STRING(tv1);
72210  DUK_ASSERT(name != NULL);
72211  act = thr->callstack + thr->callstack_top - 1;
72212  (void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/); /* -> [... val this] */
72213  duk_pop(ctx); /* 'this' binding is not needed here */
72214  DUK__REPLACE_TOP_A_BREAK();
72215  }
72216 
72217  case DUK_OP_PUTVAR: {
72218  duk_activation *act;
72219  duk_tval *tv1;
72220  duk_hstring *name;
72221 
72222  tv1 = DUK__CONSTP_BC(ins);
72223  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72224  name = DUK_TVAL_GET_STRING(tv1);
72225  DUK_ASSERT(name != NULL);
72226 
72227  /* XXX: putvar takes a duk_tval pointer, which is awkward and
72228  * should be reworked.
72229  */
72230 
72231  tv1 = DUK__REGP_A(ins); /* val */
72232  act = thr->callstack + thr->callstack_top - 1;
72233  duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
72234  break;
72235  }
72236 
72237  case DUK_OP_DELVAR: {
72238  duk_activation *act;
72239  duk_tval *tv1;
72240  duk_hstring *name;
72241  duk_bool_t rc;
72242 
72243  tv1 = DUK__CONSTP_BC(ins);
72244  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72245  name = DUK_TVAL_GET_STRING(tv1);
72246  DUK_ASSERT(name != NULL);
72247  act = thr->callstack + thr->callstack_top - 1;
72248  rc = duk_js_delvar_activation(thr, act, name);
72249  DUK__REPLACE_BOOL_A_BREAK(rc);
72250  }
72251 
72252  case DUK_OP_JUMP: {
72253  /* Note: without explicit cast to signed, MSVC will
72254  * apparently generate a large positive jump when the
72255  * bias-corrected value would normally be negative.
72256  */
72257  curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
72258  break;
72259  }
72260 
72261 #define DUK__RETURN_SHARED() do { \
72262  duk_small_uint_t ret_result; \
72263  /* duk__handle_return() is guaranteed never to throw, except \
72264  * for potential out-of-memory situations which will then \
72265  * propagate out of the executor longjmp handler. \
72266  */ \
72267  ret_result = duk__handle_return(thr, \
72268  entry_thread, \
72269  entry_callstack_top); \
72270  if (ret_result == DUK__RETHAND_RESTART) { \
72271  goto restart_execution; \
72272  } \
72273  DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
72274  return; \
72275  } while (0)
72276 #if defined(DUK_USE_EXEC_PREFER_SIZE)
72277  case DUK_OP_RETREG:
72278  case DUK_OP_RETCONST:
72279  case DUK_OP_RETCONSTN:
72280  case DUK_OP_RETUNDEF: {
72281  /* BC -> return value reg/const */
72282 
72283  DUK__SYNC_AND_NULL_CURR_PC();
72284 
72285  if (op == DUK_OP_RETREG) {
72286  duk_push_tval((duk_context *) thr, DUK__REGP_BC(ins));
72287  } else if (op == DUK_OP_RETUNDEF) {
72288  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
72289  thr->valstack_top++;
72290  } else {
72291  DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
72292  duk_push_tval((duk_context *) thr, DUK__CONSTP_BC(ins));
72293  }
72294 
72295  DUK__RETURN_SHARED();
72296  }
72297 #else /* DUK_USE_EXEC_PREFER_SIZE */
72298  case DUK_OP_RETREG: {
72299  duk_tval *tv;
72300 
72301  DUK__SYNC_AND_NULL_CURR_PC();
72302  tv = DUK__REGP_BC(ins);
72303  DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
72304  DUK_TVAL_INCREF(thr, tv);
72305  thr->valstack_top++;
72306  DUK__RETURN_SHARED();
72307  }
72308  case DUK_OP_RETCONST: {
72309  duk_tval *tv;
72310 
72311  DUK__SYNC_AND_NULL_CURR_PC();
72312  tv = DUK__CONSTP_BC(ins);
72313  DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
72314  DUK_TVAL_INCREF(thr, tv);
72315  thr->valstack_top++;
72316  DUK__RETURN_SHARED();
72317  }
72318  case DUK_OP_RETCONSTN: {
72319  duk_tval *tv;
72320 
72321  DUK__SYNC_AND_NULL_CURR_PC();
72322  tv = DUK__CONSTP_BC(ins);
72323  DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
72324  DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv)); /* no INCREF for this constant */
72325  thr->valstack_top++;
72326  DUK__RETURN_SHARED();
72327  }
72328  case DUK_OP_RETUNDEF: {
72329  DUK__SYNC_AND_NULL_CURR_PC();
72330  thr->valstack_top++; /* value at valstack top is already undefined by valstack policy */
72331  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
72332  DUK__RETURN_SHARED();
72333  }
72334 #endif /* DUK_USE_EXEC_PREFER_SIZE */
72335 
72336  case DUK_OP_LABEL: {
72337  duk_catcher *cat;
72338  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72339 
72340  /* allocate catcher and populate it (should be atomic) */
72341 
72342  duk_hthread_catchstack_grow(thr);
72343  cat = thr->catchstack + thr->catchstack_top;
72344  thr->catchstack_top++;
72345 
72346  cat->flags = DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT);
72347  cat->callstack_index = thr->callstack_top - 1;
72348  cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
72349  cat->idx_base = 0; /* unused for label */
72350  cat->h_varname = NULL;
72351 
72352  DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
72353  "idx_base=%ld, h_varname=%!O, label_id=%ld",
72354  (long) cat->flags, (long) cat->callstack_index, (long) cat->pc_base,
72355  (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
72356 
72357  curr_pc += 2; /* skip jump slots */
72358  break;
72359  }
72360 
72361  case DUK_OP_ENDLABEL: {
72362  duk_catcher *cat;
72363 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
72364  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72365 #endif
72366 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
72367  DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
72368 #endif
72369 
72370  DUK_ASSERT(thr->catchstack_top >= 1);
72371 
72372  cat = thr->catchstack + thr->catchstack_top - 1;
72373  DUK_UNREF(cat);
72374  DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
72375  DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(cat) == bc);
72376 
72377  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72378  /* no need to unwind callstack */
72379  break;
72380  }
72381 
72382  case DUK_OP_BREAK: {
72383  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72384 
72385  DUK__SYNC_AND_NULL_CURR_PC();
72386  duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
72387  goto restart_execution;
72388  }
72389 
72390  case DUK_OP_CONTINUE: {
72391  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72392 
72393  DUK__SYNC_AND_NULL_CURR_PC();
72394  duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
72395  goto restart_execution;
72396  }
72397 
72398  /* XXX: move to helper, too large to be inline here */
72399  case DUK_OP_TRYCATCH: {
72400  duk_context *ctx = (duk_context *) thr;
72401  duk_activation *act;
72402  duk_catcher *cat;
72403  duk_tval *tv1;
72404  duk_small_uint_fast_t a;
72405  duk_small_uint_fast_t bc;
72406 
72407  /* A -> flags
72408  * BC -> reg_catch; base register for two registers used both during
72409  * trycatch setup and when catch is triggered
72410  *
72411  * If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
72412  * reg_catch + 0: catch binding variable name (string).
72413  * Automatic declarative environment is established for
72414  * the duration of the 'catch' clause.
72415  *
72416  * If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
72417  * reg_catch + 0: with 'target value', which is coerced to
72418  * an object and then used as a bindind object for an
72419  * environment record. The binding is initialized here, for
72420  * the 'try' clause.
72421  *
72422  * Note that a TRYCATCH generated for a 'with' statement has no
72423  * catch or finally parts.
72424  */
72425 
72426  /* XXX: TRYCATCH handling should be reworked to avoid creating
72427  * an explicit scope unless it is actually needed (e.g. function
72428  * instances or eval is executed inside the catch block). This
72429  * rework is not trivial because the compiler doesn't have an
72430  * intermediate representation. When the rework is done, the
72431  * opcode format can also be made more straightforward.
72432  */
72433 
72434  /* XXX: side effect handling is quite awkward here */
72435 
72436  DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
72437  "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
72438  (long) DUK_DEC_BC(ins),
72439  (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
72440  (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
72441  (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
72442  (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
72443  (unsigned long) DUK_DEC_A(ins)));
72444 
72445  a = DUK_DEC_A(ins);
72446  bc = DUK_DEC_BC(ins);
72447 
72448  act = thr->callstack + thr->callstack_top - 1;
72449  DUK_ASSERT(thr->callstack_top >= 1);
72450 
72451  /* 'with' target must be created first, in case we run out of memory */
72452  /* XXX: refactor out? */
72453 
72454  if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
72455  DUK_DDD(DUK_DDDPRINT("need to initialize a with binding object"));
72456 
72457  if (act->lex_env == NULL) {
72458  DUK_ASSERT(act->var_env == NULL);
72459  DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
72460 
72461  /* must relookup act in case of side effects */
72462  duk_js_init_activation_environment_records_delayed(thr, act);
72463  act = thr->callstack + thr->callstack_top - 1;
72464  DUK_UNREF(act); /* 'act' is no longer accessed, scanbuild fix */
72465  }
72466  DUK_ASSERT(act->lex_env != NULL);
72467  DUK_ASSERT(act->var_env != NULL);
72468 
72469  (void) duk_push_object_helper(ctx,
72470  DUK_HOBJECT_FLAG_EXTENSIBLE |
72471  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
72472  -1); /* no prototype, updated below */
72473 
72474  duk_push_tval(ctx, DUK__REGP(bc));
72475  duk_to_object(ctx, -1);
72476  duk_dup_top(ctx);
72477 
72478  /* [ ... env target ] */
72479  /* [ ... env target target ] */
72480 
72481  duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
72482  duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE); /* always provideThis=true */
72483 
72484  /* [ ... env ] */
72485 
72486  DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iT",
72487  (duk_tval *) duk_get_tval(ctx, -1)));
72488  }
72489 
72490  /* allocate catcher and populate it (should be atomic) */
72491 
72492  duk_hthread_catchstack_grow(thr);
72493  cat = thr->catchstack + thr->catchstack_top;
72494  DUK_ASSERT(thr->catchstack_top + 1 <= thr->catchstack_size);
72495  thr->catchstack_top++;
72496 
72497  cat->flags = DUK_CAT_TYPE_TCF;
72498  cat->h_varname = NULL;
72499 
72500  if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
72501  cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
72502  }
72503  if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
72504  cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
72505  }
72506  if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
72507  DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
72508  cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
72509  tv1 = DUK__REGP(bc);
72510  DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
72511 
72512  /* borrowed reference; although 'tv1' comes from a register,
72513  * its value was loaded using LDCONST so the constant will
72514  * also exist and be reachable.
72515  */
72516  cat->h_varname = DUK_TVAL_GET_STRING(tv1);
72517  } else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
72518  /* env created above to stack top */
72519  duk_hobject *new_env;
72520 
72521  DUK_DDD(DUK_DDDPRINT("lexenv active flag set to catcher"));
72522  cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
72523 
72524  DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
72525  (duk_tval *) duk_get_tval(ctx, -1)));
72526  DUK_ASSERT(act->lex_env != NULL);
72527  new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
72528  DUK_ASSERT(new_env != NULL);
72529 
72530  act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
72531  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env); /* side effects */
72532 
72533  act = thr->callstack + thr->callstack_top - 1; /* relookup (side effects) */
72534  act->lex_env = new_env;
72535  DUK_HOBJECT_INCREF(thr, new_env);
72536  duk_pop(ctx);
72537  } else {
72538  ;
72539  }
72540 
72541  /* Registers 'bc' and 'bc + 1' are written in longjmp handling
72542  * and if their previous values (which are temporaries) become
72543  * unreachable -and- have a finalizer, there'll be a function
72544  * call during error handling which is not supported now (GH-287).
72545  * Ensure that both 'bc' and 'bc + 1' have primitive values to
72546  * guarantee no finalizer calls in error handling. Scrubbing also
72547  * ensures finalizers for the previous values run here rather than
72548  * later. Error handling related values are also written to 'bc'
72549  * and 'bc + 1' but those values never become unreachable during
72550  * error handling, so there's no side effect problem even if the
72551  * error value has a finalizer.
72552  */
72553  duk_to_undefined(ctx, bc);
72554  duk_to_undefined(ctx, bc + 1);
72555 
72556  cat = thr->catchstack + thr->catchstack_top - 1; /* relookup (side effects) */
72557  cat->callstack_index = thr->callstack_top - 1;
72558  cat->pc_base = (duk_instr_t *) curr_pc; /* pre-incremented, points to first jump slot */
72559  cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
72560 
72561  DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, callstack_index=%ld, pc_base=%ld, "
72562  "idx_base=%ld, h_varname=%!O",
72563  (unsigned long) cat->flags, (long) cat->callstack_index,
72564  (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
72565 
72566  curr_pc += 2; /* skip jump slots */
72567  break;
72568  }
72569 
72570  case DUK_OP_ENDTRY: {
72571  duk_catcher *cat;
72572  duk_tval *tv1;
72573 
72574  DUK_ASSERT(thr->catchstack_top >= 1);
72575  DUK_ASSERT(thr->callstack_top >= 1);
72576  DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
72577 
72578  cat = thr->catchstack + thr->catchstack_top - 1;
72579 
72580  DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
72581  DUK_CAT_CLEAR_CATCH_ENABLED(cat);
72582 
72583  if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
72584  DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
72585 
72586  tv1 = thr->valstack + cat->idx_base;
72587  DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
72588  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
72589  tv1 = NULL;
72590 
72591  tv1 = thr->valstack + cat->idx_base + 1;
72592  DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
72593  DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
72594  tv1 = NULL;
72595 
72596  DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
72597  } else {
72598  DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
72599  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72600  /* no need to unwind callstack */
72601  }
72602 
72603  curr_pc = cat->pc_base + 1;
72604  break;
72605  }
72606 
72607  case DUK_OP_ENDCATCH: {
72608  duk_activation *act;
72609  duk_catcher *cat;
72610  duk_tval *tv1;
72611 
72612  DUK_ASSERT(thr->catchstack_top >= 1);
72613  DUK_ASSERT(thr->callstack_top >= 1);
72614  DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
72615 
72616  cat = thr->catchstack + thr->catchstack_top - 1;
72617  DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat)); /* cleared before entering catch part */
72618 
72619  act = thr->callstack + thr->callstack_top - 1;
72620 
72621  if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
72622  duk_hobject *prev_env;
72623 
72624  /* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
72625  DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
72626  DUK_ASSERT(act->lex_env != NULL);
72627 
72628  DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
72629 
72630  prev_env = act->lex_env;
72631  DUK_ASSERT(prev_env != NULL);
72632  act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
72633  DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
72634  DUK_HOBJECT_DECREF(thr, prev_env); /* side effects */
72635  }
72636 
72637  if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
72638  DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
72639 
72640  tv1 = thr->valstack + cat->idx_base;
72641  DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
72642  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1); /* side effects */
72643  tv1 = NULL;
72644 
72645  tv1 = thr->valstack + cat->idx_base + 1;
72646  DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
72647  DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL); /* side effects */
72648  tv1 = NULL;
72649 
72650  DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
72651  } else {
72652  DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
72653  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72654  /* no need to unwind callstack */
72655  }
72656 
72657  curr_pc = cat->pc_base + 1;
72658  break;
72659  }
72660 
72661  case DUK_OP_ENDFIN: {
72662  duk_context *ctx = (duk_context *) thr;
72663  duk_catcher *cat;
72664  duk_tval *tv1;
72665  duk_small_uint_t cont_type;
72666  duk_small_uint_t ret_result;
72667 
72668  /* Sync and NULL early. */
72669  DUK__SYNC_AND_NULL_CURR_PC();
72670 
72671  DUK_ASSERT(thr->catchstack_top >= 1);
72672  DUK_ASSERT(thr->callstack_top >= 1);
72673  DUK_ASSERT(thr->catchstack[thr->catchstack_top - 1].callstack_index == thr->callstack_top - 1);
72674 
72675  cat = thr->catchstack + thr->catchstack_top - 1;
72676 
72677  /* CATCH flag may be enabled or disabled here; it may be enabled if
72678  * the statement has a catch block but the try block does not throw
72679  * an error.
72680  */
72681  DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
72682  /* XXX: assert idx_base */
72683 
72684  DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
72685  (duk_tval *) (thr->valstack + cat->idx_base + 0),
72686  (duk_tval *) (thr->valstack + cat->idx_base + 1)));
72687 
72688  tv1 = thr->valstack + cat->idx_base + 1; /* type */
72689  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
72690  cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
72691 
72692  switch (cont_type) {
72693  case DUK_LJ_TYPE_NORMAL: {
72694  DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
72695  "dismantle catcher, resume execution after ENDFIN"));
72696  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72697  /* no need to unwind callstack */
72698  goto restart_execution;
72699  }
72700  case DUK_LJ_TYPE_RETURN: {
72701  DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
72702  "catcher, handle return, lj.value1=%!T", thr->valstack + cat->idx_base));
72703 
72704  /* Not necessary to unwind catchstack: return handling will
72705  * do it. The finally flag of 'cat' is no longer set. The
72706  * catch flag may be set, but it's not checked by return handling.
72707  */
72708  DUK_ASSERT(!DUK_CAT_HAS_FINALLY_ENABLED(cat)); /* cleared before entering finally */
72709 #if 0
72710  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72711 #endif
72712 
72713  duk_push_tval(ctx, thr->valstack + cat->idx_base);
72714  ret_result = duk__handle_return(thr,
72715  entry_thread,
72716  entry_callstack_top);
72717  if (ret_result == DUK__RETHAND_RESTART) {
72718  goto restart_execution;
72719  }
72720  DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
72721 
72722  DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
72723  return;
72724  }
72725  case DUK_LJ_TYPE_BREAK:
72726  case DUK_LJ_TYPE_CONTINUE: {
72727  duk_uint_t label_id;
72728  duk_small_uint_t lj_type;
72729 
72730  /* Not necessary to unwind catchstack: break/continue
72731  * handling will do it. The finally flag of 'cat' is
72732  * no longer set. The catch flag may be set, but it's
72733  * not checked by break/continue handling.
72734  */
72735 #if 0
72736  duk_hthread_catchstack_unwind(thr, thr->catchstack_top - 1);
72737 #endif
72738 
72739  tv1 = thr->valstack + cat->idx_base;
72740  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
72741 #if defined(DUK_USE_FASTINT)
72742  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
72743  label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
72744 #else
72745  label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
72746 #endif
72747  lj_type = cont_type;
72748  duk__handle_break_or_continue(thr, label_id, lj_type);
72749  goto restart_execution;
72750  }
72751  default: {
72752  DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
72753  "dismantle catcher, re-throw error",
72754  (long) cont_type));
72755 
72756  duk_push_tval(ctx, thr->valstack + cat->idx_base);
72757 
72758  duk_err_setup_heap_ljstate(thr, (duk_small_int_t) cont_type);
72759 
72760  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
72761  duk_err_longjmp(thr);
72762  DUK_UNREACHABLE();
72763  }
72764  }
72765 
72766  /* Must restart in all cases because we NULLed thr->ptr_curr_pc. */
72767  DUK_UNREACHABLE();
72768  break;
72769  }
72770 
72771  case DUK_OP_THROW: {
72772  duk_context *ctx = (duk_context *) thr;
72773  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72774 
72775  /* Note: errors are augmented when they are created, not
72776  * when they are thrown. So, don't augment here, it would
72777  * break re-throwing for instance.
72778  */
72779 
72780  /* Sync so that augmentation sees up-to-date activations, NULL
72781  * thr->ptr_curr_pc so that it's not used if side effects occur
72782  * in augmentation or longjmp handling.
72783  */
72784  DUK__SYNC_AND_NULL_CURR_PC();
72785 
72786  duk_dup(ctx, (duk_idx_t) bc);
72787  DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
72788  (duk_tval *) duk_get_tval(ctx, -1)));
72789 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
72790  duk_err_augment_error_throw(thr);
72791  DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
72792  (duk_tval *) duk_get_tval(ctx, -1)));
72793 #endif
72794 
72795  duk_err_setup_heap_ljstate(thr, DUK_LJ_TYPE_THROW);
72796 
72797  DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL); /* always in executor */
72798  duk_err_longjmp(thr);
72799  DUK_UNREACHABLE();
72800  break;
72801  }
72802 
72803  case DUK_OP_CSREG: {
72804  /*
72805  * Assuming a register binds to a variable declared within this
72806  * function (a declarative binding), the 'this' for the call
72807  * setup is always 'undefined'. E5 Section 10.2.1.1.6.
72808  */
72809 
72810  duk_small_uint_fast_t a = DUK_DEC_A(ins);
72811  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72812 
72813  /* A -> register containing target function (not type checked here)
72814  * BC -> target registers (BC, BC + 1) for call setup
72815  */
72816 
72817 #if defined(DUK_USE_PREFER_SIZE)
72818  duk_dup((duk_context *) thr, a);
72819  duk_replace((duk_context *) thr, bc);
72820  duk_to_undefined((duk_context *) thr, bc + 1);
72821 #else
72822  duk_tval *tv1;
72823  duk_tval *tv2;
72824  duk_tval *tv3;
72825  duk_tval tv_tmp1;
72826  duk_tval tv_tmp2;
72827 
72828  tv1 = DUK__REGP(bc);
72829  tv2 = tv1 + 1;
72830  DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
72831  DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
72832  tv3 = DUK__REGP(a);
72833  DUK_TVAL_SET_TVAL(tv1, tv3);
72834  DUK_TVAL_INCREF(thr, tv1); /* no side effects */
72835  DUK_TVAL_SET_UNDEFINED(tv2); /* no need for incref */
72836  DUK_TVAL_DECREF(thr, &tv_tmp1);
72837  DUK_TVAL_DECREF(thr, &tv_tmp2);
72838 #endif
72839  break;
72840  }
72841 
72842  case DUK_OP_EVALCALL: {
72843  /* Eval call or a normal call made using the identifier 'eval'.
72844  * Eval calls are never handled as tail calls for simplicity.
72845  */
72846  duk_context *ctx = (duk_context *) thr;
72847  duk_small_uint_fast_t nargs;
72848  duk_uint_fast_t idx;
72849  duk_idx_t num_stack_args;
72850  duk_small_uint_t call_flags;
72851  duk_tval *tv_func;
72852  duk_hobject *obj_func;
72853 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
72854  duk_hcompfunc *fun;
72855 #endif
72856 
72857  /* Technically we should also check for the possibility of
72858  * a pure Ecmascript-to-Ecmascript call: while built-in eval()
72859  * is native, it's possible for the 'eval' identifier to be
72860  * shadowed. In practice that would be rare and optimizing the
72861  * C call stack for that case is a bit pointless.
72862  */
72863 
72864  nargs = (duk_small_uint_fast_t) DUK_DEC_A(ins);
72865  idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
72866  duk_set_top(ctx, (duk_idx_t) (idx + nargs + 2)); /* [ ... func this arg1 ... argN ] */
72867 
72868  call_flags = 0;
72869  tv_func = DUK_GET_TVAL_POSIDX(ctx, idx);
72870  if (DUK_TVAL_IS_OBJECT(tv_func)) {
72871  obj_func = DUK_TVAL_GET_OBJECT(tv_func);
72872  DUK_ASSERT(obj_func != NULL);
72873  if (DUK_HOBJECT_IS_NATFUNC(obj_func) &&
72874  ((duk_hnatfunc *) obj_func)->func == duk_bi_global_object_eval) {
72875  DUK_DDD(DUK_DDDPRINT("call target is eval, call identifier was 'eval' -> direct eval"));
72876  call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
72877  }
72878  }
72879  num_stack_args = nargs;
72880  duk_handle_call_unprotected(thr, num_stack_args, call_flags);
72881 
72882 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
72883  fun = DUK__FUN();
72884 #endif
72885  duk_set_top(ctx, (duk_idx_t) fun->nregs);
72886  break;
72887  }
72888 
72889  case DUK_OP_CALL:
72890  case DUK_OP_TAILCALL: {
72891  /* DUK_OP_CALL: plain call, not tailcall compatible.
72892  *
72893  * DUK_OP_TAILCALL: plain call which is tailcall
72894  * compatible. Tail call may not be possible due
72895  * to e.g. target not being an Ecmascript function.
72896  *
72897  * Not a direct eval call. Indirect eval calls don't
72898  * need special handling here.
72899  */
72900 
72901  /* To determine whether to use an optimized Ecmascript-to-Ecmascript
72902  * call, we need to know whether the final, non-bound function is an
72903  * Ecmascript function. Current implementation is to first try an
72904  * Ecma-to-Ecma call setup which also resolves the bound function
72905  * chain. The setup attempt overwrites call target at DUK__REGP(idx)
72906  * and may also fudge the argument list. However, it won't resolve
72907  * the effective 'this' binding if the setup fails. This is somewhat
72908  * awkward, and the two call setup code paths should be merged.
72909  *
72910  * If an Ecma-to-Ecma call is not possible, the actual call handling
72911  * will do another (unnecessary) attempt to resolve the bound function.
72912  */
72913 
72914  duk_context *ctx = (duk_context *) thr;
72915  duk_small_uint_fast_t nargs;
72916  duk_uint_fast_t idx;
72917  duk_idx_t num_stack_args;
72918  duk_small_uint_t call_flags;
72919 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
72920  duk_hcompfunc *fun;
72921 #endif
72922 
72923  /* A -> nargs
72924  * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
72925  */
72926 
72927  /* XXX: in some cases it's faster NOT to reuse the value
72928  * stack but rather copy the arguments on top of the stack
72929  * (mainly when the calling value stack is large and the value
72930  * stack resize would be large). See DUK_OP_NEW.
72931  */
72932 
72933  nargs = (duk_small_uint_fast_t) DUK_DEC_A(ins);
72934  idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
72935  duk_set_top(ctx, (duk_idx_t) (idx + nargs + 2)); /* [ ... func this arg1 ... argN ] */
72936 
72937  /* DUK_OP_CALL and DUK_OP_TAILCALL are consecutive
72938  * which allows a simple bit test.
72939  */
72940  DUK_ASSERT((DUK_OP_CALL & 0x01) == 0);
72941  DUK_ASSERT((DUK_OP_TAILCALL & 0x01) == 1);
72942  call_flags = (ins & (1UL << DUK_BC_SHIFT_OP)) ? DUK_CALL_FLAG_IS_TAILCALL : 0;
72943 
72944  num_stack_args = nargs;
72945  if (duk_handle_ecma_call_setup(thr, num_stack_args, call_flags)) {
72946  /* Ecma-to-ecma call possible, may or may not be a tail call.
72947  * Avoid C recursion by being clever.
72948  */
72949  DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
72950  /* curr_pc synced by duk_handle_ecma_call_setup() */
72951  goto restart_execution;
72952  }
72953 
72954  /* Recompute argument count: bound function handling may have shifted. */
72955  num_stack_args = duk_get_top(ctx) - (idx + 2);
72956  DUK_DDD(DUK_DDDPRINT("recomputed arg count: %ld\n", (long) num_stack_args));
72957 
72958  /* Target is either a lightfunc or a function object.
72959  * We don't need to check for eval handling here: the
72960  * call may be an indirect eval ('myEval("something")')
72961  * but that requires no special handling.
72962  */
72963 
72964  duk_handle_call_unprotected(thr, num_stack_args, 0 /*call_flags*/);
72965 
72966  /* duk_js_call.c is required to restore the stack reserve
72967  * so we only need to reset the top.
72968  */
72969 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
72970  fun = DUK__FUN();
72971 #endif
72972  duk_set_top(ctx, (duk_idx_t) fun->nregs);
72973 
72974  /* No need to reinit setjmp() catchpoint, as call handling
72975  * will store and restore our state.
72976  */
72977 
72978  /* When debugger is enabled, we need to recheck the activation
72979  * status after returning. This is now handled by call handling
72980  * and heap->dbg_force_restart.
72981  */
72982  break;
72983  }
72984 
72985  case DUK_OP_NEW: {
72986  duk_context *ctx = (duk_context *) thr;
72987  duk_small_uint_fast_t a = DUK_DEC_A(ins);
72988  duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
72989 #if defined(DUK_USE_EXEC_PREFER_SIZE)
72990 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
72991  duk_hcompfunc *fun;
72992 #endif
72993 #else
72994  duk_small_uint_fast_t count;
72995  duk_tval *tv_src;
72996 #endif
72997 
72998  /* A -> num args (N)
72999  * BC -> target register and start reg: constructor, arg1, ..., argN
73000  */
73001 
73002  /* duk_new() will call the constuctor using duk_handle_call().
73003  * A constructor call prevents a yield from inside the constructor,
73004  * even if the constructor is an Ecmascript function.
73005  */
73006 
73007  /* Don't need to sync curr_pc here; duk_new() will do that
73008  * when it augments the created error.
73009  */
73010 
73011 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73012  /* This alternative relies on our being allowed to trash anything
73013  * above 'bc' so we can just reuse the argument registers which
73014  * means smaller value stack use. Footprint is a bit smaller.
73015  */
73016  duk_set_top(ctx, (duk_idx_t) (bc + a + 1));
73017  duk_new(ctx, (duk_idx_t) a); /* [... constructor arg1 ... argN] -> [retval] */
73018 
73019  /* The return value is already in its correct place at the stack,
73020  * i.e. it has replaced the 'constructor' at index bc. Just reset
73021  * top and we're done.
73022  */
73023 
73024 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
73025  fun = DUK__FUN();
73026 #endif
73027  duk_set_top(ctx, (duk_idx_t) fun->nregs);
73028 #else /* DUK_USE_EXEC_PREFER_SIZE */
73029  /* Faster alternative is to duplicate the values to avoid a resize.
73030  * This depends on the relative size between the value stack and
73031  * the argument count, though.
73032  */
73033  count = a + 1;
73034  duk_require_stack(ctx, count);
73035  tv_src = DUK_GET_TVAL_POSIDX(ctx, bc);
73036  duk__push_tvals_incref_only(thr, tv_src, count);
73037  duk_new(ctx, (duk_idx_t) a); /* [... constructor arg1 ... argN] -> [retval] */
73038  duk_replace(ctx, bc);
73039 #endif /* DUK_USE_EXEC_PREFER_SIZE */
73040 
73041  /* When debugger is enabled, we need to recheck the activation
73042  * status after returning. This is now handled by call handling
73043  * and heap->dbg_force_restart.
73044  */
73045  break;
73046  }
73047 
73048  case DUK_OP_NEWOBJ: {
73049  duk_context *ctx = (duk_context *) thr;
73050  duk_push_object(ctx);
73051  DUK__REPLACE_TOP_BC_BREAK();
73052  }
73053 
73054  case DUK_OP_NEWARR: {
73055  duk_context *ctx = (duk_context *) thr;
73056  duk_push_array(ctx);
73057  DUK__REPLACE_TOP_BC_BREAK();
73058  }
73059 
73060  case DUK_OP_MPUTOBJ:
73061  case DUK_OP_MPUTOBJI: {
73062  duk_context *ctx = (duk_context *) thr;
73063  duk_idx_t obj_idx;
73064  duk_uint_fast_t idx, idx_end;
73065  duk_small_uint_fast_t count;
73066 
73067  /* A -> register of target object
73068  * B -> first register of key/value pair list
73069  * or register containing first register number if indirect
73070  * C -> number of key/value pairs * 2
73071  * (= number of value stack indices used starting from 'B')
73072  */
73073 
73074  obj_idx = DUK_DEC_A(ins);
73075  DUK_ASSERT(duk_is_object(ctx, obj_idx));
73076 
73077  idx = (duk_uint_fast_t) DUK_DEC_B(ins);
73078  if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
73079  DUK__LOOKUP_INDIRECT_INDEX(idx);
73080  }
73081 
73082  count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
73083  DUK_ASSERT(count > 0); /* compiler guarantees */
73084  idx_end = idx + count;
73085 
73086 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
73087  if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(ctx))) {
73088  /* XXX: use duk_is_valid_index() instead? */
73089  /* XXX: improve check; check against nregs, not against top */
73090  DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
73091  }
73092 #endif
73093 
73094  /* Use 'force' flag to duk_def_prop() to ensure that any
73095  * inherited properties don't prevent the operation.
73096  * With ES2015 duplicate properties are allowed, so that we
73097  * must overwrite any previous data or accessor property.
73098  *
73099  * With ES2015 computed property names the literal keys
73100  * may be arbitrary values and need to be ToPropertyKey()
73101  * coerced at runtime.
73102  */
73103  do {
73104  /* XXX: faster initialization (direct access or better primitives) */
73105  duk_dup(ctx, idx);
73106  duk_dup(ctx, idx + 1);
73107  duk_def_prop(ctx, obj_idx, DUK_DEFPROP_HAVE_VALUE |
73108  DUK_DEFPROP_FORCE |
73109  DUK_DEFPROP_SET_WRITABLE |
73110  DUK_DEFPROP_SET_ENUMERABLE |
73111  DUK_DEFPROP_SET_CONFIGURABLE);
73112  idx += 2;
73113  } while (idx < idx_end);
73114  break;
73115  }
73116 
73117  case DUK_OP_INITSET:
73118  case DUK_OP_INITGET: {
73119  duk_context *ctx = (duk_context *) thr;
73120  duk_bool_t is_set = (op == DUK_OP_INITSET);
73121  duk_uint_fast_t idx;
73122  duk_uint_t defprop_flags;
73123 
73124  /* A -> object register (acts as a source)
73125  * BC -> BC+0 contains key, BC+1 closure (value)
73126  */
73127 
73128  /* INITSET/INITGET are only used to initialize object literal keys.
73129  * There may be a previous propery in ES2015 because duplicate property
73130  * names are allowed.
73131  */
73132 
73133  /* This could be made more optimal by accessing internals directly. */
73134 
73135  idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
73136  duk_dup(ctx, (duk_idx_t) (idx + 0)); /* key */
73137  duk_dup(ctx, (duk_idx_t) (idx + 1)); /* getter/setter */
73138  if (is_set) {
73139  defprop_flags = DUK_DEFPROP_HAVE_SETTER |
73140  DUK_DEFPROP_FORCE |
73141  DUK_DEFPROP_SET_ENUMERABLE |
73142  DUK_DEFPROP_SET_CONFIGURABLE;
73143  } else {
73144  defprop_flags = DUK_DEFPROP_HAVE_GETTER |
73145  DUK_DEFPROP_FORCE |
73146  DUK_DEFPROP_SET_ENUMERABLE |
73147  DUK_DEFPROP_SET_CONFIGURABLE;
73148  }
73149  duk_def_prop(ctx, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
73150  break;
73151  }
73152 
73153  case DUK_OP_MPUTARR:
73154  case DUK_OP_MPUTARRI: {
73155  duk_context *ctx = (duk_context *) thr;
73156  duk_idx_t obj_idx;
73157  duk_uint_fast_t idx, idx_end;
73158  duk_small_uint_fast_t count;
73159  duk_tval *tv1;
73160  duk_uint32_t arr_idx;
73161 
73162  /* A -> register of target object
73163  * B -> first register of value data (start_index, value1, value2, ..., valueN)
73164  * or register containing first register number if indirect
73165  * C -> number of key/value pairs (N)
73166  */
73167 
73168  obj_idx = DUK_DEC_A(ins);
73169  DUK_ASSERT(duk_is_object(ctx, obj_idx));
73170 
73171  idx = (duk_uint_fast_t) DUK_DEC_B(ins);
73172  if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
73173  DUK__LOOKUP_INDIRECT_INDEX(idx);
73174  }
73175 
73176  count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
73177  DUK_ASSERT(count > 0 + 1); /* compiler guarantees */
73178  idx_end = idx + count;
73179 
73180 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
73181  if (idx_end > (duk_uint_fast_t) duk_get_top(ctx)) {
73182  /* XXX: use duk_is_valid_index() instead? */
73183  /* XXX: improve check; check against nregs, not against top */
73184  DUK__INTERNAL_ERROR("MPUTARR out of bounds");
73185  }
73186 #endif
73187 
73188  tv1 = DUK__REGP(idx);
73189  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
73190 #if defined(DUK_USE_FASTINT)
73191  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
73192  arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
73193 #else
73194  arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
73195 #endif
73196  idx++;
73197 
73198  do {
73199  /* duk_xdef_prop() will define an own property without any array
73200  * special behaviors. We'll need to set the array length explicitly
73201  * in the end. For arrays with elisions, the compiler will emit an
73202  * explicit SETALEN which will update the length.
73203  */
73204 
73205  /* XXX: because we're dealing with 'own' properties of a fresh array,
73206  * the array initializer should just ensure that the array has a large
73207  * enough array part and write the values directly into array part,
73208  * and finally set 'length' manually in the end (as already happens now).
73209  */
73210 
73211  duk_dup(ctx, idx);
73212  duk_xdef_prop_index_wec(ctx, obj_idx, arr_idx);
73213 
73214  idx++;
73215  arr_idx++;
73216  } while (idx < idx_end);
73217 
73218  /* XXX: E5.1 Section 11.1.4 coerces the final length through
73219  * ToUint32() which is odd but happens now as a side effect of
73220  * 'arr_idx' type.
73221  */
73222  duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
73223  break;
73224  }
73225 
73226  case DUK_OP_SETALEN: {
73227  duk_tval *tv1;
73228  duk_hobject *h;
73229  duk_uint32_t len;
73230 
73231  tv1 = DUK__REGP_A(ins);
73232  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
73233  h = DUK_TVAL_GET_OBJECT(tv1);
73234  DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
73235 
73236  tv1 = DUK__REGP_BC(ins);
73237  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
73238 #if defined(DUK_USE_FASTINT)
73239  DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
73240  len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
73241 #else
73242  len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
73243 #endif
73244  ((duk_harray *) h)->length = len;
73245  break;
73246  }
73247 
73248  case DUK_OP_INITENUM: {
73249  duk_context *ctx = (duk_context *) thr;
73250  duk_small_uint_fast_t b = DUK_DEC_B(ins);
73251  duk_small_uint_fast_t c = DUK_DEC_C(ins);
73252 
73253  /*
73254  * Enumeration semantics come from for-in statement, E5 Section 12.6.4.
73255  * If called with 'null' or 'undefined', this opcode returns 'null' as
73256  * the enumerator, which is special cased in NEXTENUM. This simplifies
73257  * the compiler part
73258  */
73259 
73260  /* B -> register for writing enumerator object
73261  * C -> value to be enumerated (register)
73262  */
73263 
73264  if (duk_is_null_or_undefined(ctx, (duk_idx_t) c)) {
73265  duk_push_null(ctx);
73266  duk_replace(ctx, (duk_idx_t) b);
73267  } else {
73268  duk_dup(ctx, (duk_idx_t) c);
73269  duk_to_object(ctx, -1);
73270  duk_hobject_enumerator_create(ctx, 0 /*enum_flags*/); /* [ ... val ] --> [ ... enum ] */
73271  duk_replace(ctx, (duk_idx_t) b);
73272  }
73273  break;
73274  }
73275 
73276  case DUK_OP_NEXTENUM: {
73277  duk_context *ctx = (duk_context *) thr;
73278  duk_small_uint_fast_t b = DUK_DEC_B(ins);
73279  duk_small_uint_fast_t c = DUK_DEC_C(ins);
73280 
73281  /*
73282  * NEXTENUM checks whether the enumerator still has unenumerated
73283  * keys. If so, the next key is loaded to the target register
73284  * and the next instruction is skipped. Otherwise the next instruction
73285  * will be executed, jumping out of the enumeration loop.
73286  */
73287 
73288  /* B -> target register for next key
73289  * C -> enum register
73290  */
73291 
73292  DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
73293  (duk_tval *) duk_get_tval(ctx, (duk_idx_t) b),
73294  (duk_tval *) duk_get_tval(ctx, (duk_idx_t) c)));
73295 
73296  if (duk_is_object(ctx, (duk_idx_t) c)) {
73297  /* XXX: assert 'c' is an enumerator */
73298  duk_dup(ctx, (duk_idx_t) c);
73299  if (duk_hobject_enumerator_next(ctx, 0 /*get_value*/)) {
73300  /* [ ... enum ] -> [ ... next_key ] */
73301  DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
73302  (duk_tval *) duk_get_tval(ctx, -1)));
73303  curr_pc++;
73304  } else {
73305  /* [ ... enum ] -> [ ... ] */
73306  DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
73307  DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top)); /* valstack policy */
73308  thr->valstack_top++;
73309  }
73310  duk_replace(ctx, (duk_idx_t) b);
73311  } else {
73312  /* 'null' enumerator case -> behave as with an empty enumerator */
73313  DUK_ASSERT(duk_is_null(ctx, (duk_idx_t) c));
73314  DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
73315  }
73316  break;
73317  }
73318 
73319  case DUK_OP_INVLHS: {
73320  DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
73321  DUK_UNREACHABLE();
73322  break;
73323  }
73324 
73325  case DUK_OP_DEBUGGER: {
73326  /* Opcode only emitted by compiler when debugger
73327  * support is enabled. Ignore it silently without
73328  * debugger support, in case it has been loaded
73329  * from precompiled bytecode.
73330  */
73331 #if defined(DUK_USE_DEBUGGER_SUPPORT)
73332  if (DUK_HEAP_IS_DEBUGGER_ATTACHED(thr->heap)) {
73333  DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
73334  DUK__SYNC_AND_NULL_CURR_PC();
73335  duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
73336  DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
73337  goto restart_execution;
73338  } else {
73339  DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
73340  }
73341 #else
73342  DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
73343 #endif
73344  break;
73345  }
73346 
73347  case DUK_OP_NOP: {
73348  /* nop */
73349  break;
73350  }
73351 
73352  case DUK_OP_INVALID: {
73353  DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
73354  break;
73355  }
73356 
73357 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
73358 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
73359  case DUK_OP_EXP_RR:
73360  case DUK_OP_EXP_CR:
73361  case DUK_OP_EXP_RC:
73362  case DUK_OP_EXP_CC:
73363 #endif
73364  case DUK_OP_UNUSED194:
73365  case DUK_OP_UNUSED195:
73366  case DUK_OP_UNUSED196:
73367  case DUK_OP_UNUSED197:
73368  case DUK_OP_UNUSED198:
73369  case DUK_OP_UNUSED199:
73370  case DUK_OP_UNUSED200:
73371  case DUK_OP_UNUSED201:
73372  case DUK_OP_UNUSED202:
73373  case DUK_OP_UNUSED203:
73374  case DUK_OP_UNUSED204:
73375  case DUK_OP_UNUSED205:
73376  case DUK_OP_UNUSED206:
73377  case DUK_OP_UNUSED207:
73378  case DUK_OP_UNUSED208:
73379  case DUK_OP_UNUSED209:
73380  case DUK_OP_UNUSED210:
73381  case DUK_OP_UNUSED211:
73382  case DUK_OP_UNUSED212:
73383  case DUK_OP_UNUSED213:
73384  case DUK_OP_UNUSED214:
73385  case DUK_OP_UNUSED215:
73386  case DUK_OP_UNUSED216:
73387  case DUK_OP_UNUSED217:
73388  case DUK_OP_UNUSED218:
73389  case DUK_OP_UNUSED219:
73390  case DUK_OP_UNUSED220:
73391  case DUK_OP_UNUSED221:
73392  case DUK_OP_UNUSED222:
73393  case DUK_OP_UNUSED223:
73394  case DUK_OP_UNUSED224:
73395  case DUK_OP_UNUSED225:
73396  case DUK_OP_UNUSED226:
73397  case DUK_OP_UNUSED227:
73398  case DUK_OP_UNUSED228:
73399  case DUK_OP_UNUSED229:
73400  case DUK_OP_UNUSED230:
73401  case DUK_OP_UNUSED231:
73402  case DUK_OP_UNUSED232:
73403  case DUK_OP_UNUSED233:
73404  case DUK_OP_UNUSED234:
73405  case DUK_OP_UNUSED235:
73406  case DUK_OP_UNUSED236:
73407  case DUK_OP_UNUSED237:
73408  case DUK_OP_UNUSED238:
73409  case DUK_OP_UNUSED239:
73410  case DUK_OP_UNUSED240:
73411  case DUK_OP_UNUSED241:
73412  case DUK_OP_UNUSED242:
73413  case DUK_OP_UNUSED243:
73414  case DUK_OP_UNUSED244:
73415  case DUK_OP_UNUSED245:
73416  case DUK_OP_UNUSED246:
73417  case DUK_OP_UNUSED247:
73418  case DUK_OP_UNUSED248:
73419  case DUK_OP_UNUSED249:
73420  case DUK_OP_UNUSED250:
73421  case DUK_OP_UNUSED251:
73422  case DUK_OP_UNUSED252:
73423  case DUK_OP_UNUSED253:
73424  case DUK_OP_UNUSED254:
73425  case DUK_OP_UNUSED255: {
73426  /* Force all case clauses to map to an actual handler
73427  * so that the compiler can emit a jump without a bounds
73428  * check: the switch argument is a duk_uint8_t so that
73429  * the compiler may be able to figure it out. This is
73430  * a small detail and obviously compiler dependent.
73431  */
73432  volatile duk_small_int_t dummy_volatile;
73433  dummy_volatile = 0;
73434  DUK_UNREF(dummy_volatile);
73435  DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
73436  DUK__INTERNAL_ERROR("invalid opcode");
73437  break;
73438  }
73439 #endif /* DUK_USE_EXEC_PREFER_SIZE */
73440  default: {
73441  /* Default case catches invalid/unsupported opcodes. */
73442  DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
73443  DUK__INTERNAL_ERROR("invalid opcode");
73444  break;
73445  }
73446 
73447  } /* end switch */
73448 
73449  continue;
73450 
73451  /* Some shared exit paths for opcode handling below. These
73452  * are mostly useful to reduce code footprint when multiple
73453  * opcodes have a similar epilogue (like replacing stack top
73454  * with index 'a').
73455  */
73456 
73457 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73458  replace_top_a:
73459  DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
73460  continue;
73461  replace_top_bc:
73462  DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
73463  continue;
73464 #endif
73465  }
73466  DUK_UNREACHABLE();
73467 
73468 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
73469  internal_error:
73470  DUK_ERROR_INTERNAL(thr);
73471 #endif
73472 }
73473 
73474 /* automatic undefs */
73475 #undef DUK__BYTEOFF_A
73476 #undef DUK__BYTEOFF_B
73477 #undef DUK__BYTEOFF_BC
73478 #undef DUK__BYTEOFF_C
73479 #undef DUK__COMPARE_BODY
73480 #undef DUK__CONST
73481 #undef DUK__CONSTP
73482 #undef DUK__CONSTP_A
73483 #undef DUK__CONSTP_B
73484 #undef DUK__CONSTP_BC
73485 #undef DUK__CONSTP_C
73486 #undef DUK__DELPROP_BODY
73487 #undef DUK__EQ_BODY
73488 #undef DUK__FUN
73489 #undef DUK__GETPROP_BODY
73490 #undef DUK__GE_BODY
73491 #undef DUK__GT_BODY
73492 #undef DUK__INLINE_PERF
73493 #undef DUK__INSTOF_BODY
73494 #undef DUK__INTERNAL_ERROR
73495 #undef DUK__INT_NOACTION
73496 #undef DUK__INT_RESTART
73497 #undef DUK__IN_BODY
73498 #undef DUK__LE_BODY
73499 #undef DUK__LONGJMP_RESTART
73500 #undef DUK__LONGJMP_RETHROW
73501 #undef DUK__LOOKUP_INDIRECT_INDEX
73502 #undef DUK__LT_BODY
73503 #undef DUK__MASK_A
73504 #undef DUK__MASK_B
73505 #undef DUK__MASK_BC
73506 #undef DUK__MASK_C
73507 #undef DUK__NEQ_BODY
73508 #undef DUK__PUTPROP_BODY
73509 #undef DUK__RCBIT_B
73510 #undef DUK__RCBIT_C
73511 #undef DUK__REG
73512 #undef DUK__REGCONSTP_B
73513 #undef DUK__REGCONSTP_C
73514 #undef DUK__REGP
73515 #undef DUK__REGP_A
73516 #undef DUK__REGP_B
73517 #undef DUK__REGP_BC
73518 #undef DUK__REGP_C
73519 #undef DUK__REPLACE_BOOL_A_BREAK
73520 #undef DUK__REPLACE_TOP_A_BREAK
73521 #undef DUK__REPLACE_TOP_BC_BREAK
73522 #undef DUK__REPLACE_TO_TVPTR
73523 #undef DUK__RETHAND_FINISHED
73524 #undef DUK__RETHAND_RESTART
73525 #undef DUK__RETURN_SHARED
73526 #undef DUK__SEQ_BODY
73527 #undef DUK__SHIFT_A
73528 #undef DUK__SHIFT_B
73529 #undef DUK__SHIFT_BC
73530 #undef DUK__SHIFT_C
73531 #undef DUK__SNEQ_BODY
73532 #undef DUK__STRICT
73533 #undef DUK__SYNC_AND_NULL_CURR_PC
73534 #undef DUK__SYNC_CURR_PC
73535 #undef DUK__TVAL_SHIFT
73536 /*
73537  * Ecmascript specification algorithm and conversion helpers.
73538  *
73539  * These helpers encapsulate the primitive Ecmascript operation semantics,
73540  * and are used by the bytecode executor and the API (among other places).
73541  * Some primitives are only implemented as part of the API and have no
73542  * "internal" helper. This is the case when an internal helper would not
73543  * really be useful; e.g. the operation is rare, uses value stack heavily,
73544  * etc.
73545  *
73546  * The operation arguments depend on what is required to implement
73547  * the operation:
73548  *
73549  * - If an operation is simple and stateless, and has no side
73550  * effects, it won't take an duk_hthread argument and its
73551  * arguments may be duk_tval pointers (which are safe as long
73552  * as no side effects take place).
73553  *
73554  * - If complex coercions are required (e.g. a "ToNumber" coercion)
73555  * or errors may be thrown, the operation takes an duk_hthread
73556  * argument. This also implies that the operation may have
73557  * arbitrary side effects, invalidating any duk_tval pointers.
73558  *
73559  * - For operations with potential side effects, arguments can be
73560  * taken in several ways:
73561  *
73562  * a) as duk_tval pointers, which makes sense if the "common case"
73563  * can be resolved without side effects (e.g. coercion); the
73564  * arguments are pushed to the valstack for coercion if
73565  * necessary
73566  *
73567  * b) as duk_tval values
73568  *
73569  * c) implicitly on value stack top
73570  *
73571  * d) as indices to the value stack
73572  *
73573  * Future work:
73574  *
73575  * - Argument styles may not be the most sensible in every case now.
73576  *
73577  * - In-place coercions might be useful for several operations, if
73578  * in-place coercion is OK for the bytecode executor and the API.
73579  */
73580 
73581 /* #include duk_internal.h -> already included */
73582 
73583 /*
73584  * ToPrimitive() (E5 Section 9.1)
73585  *
73586  * ==> implemented in the API.
73587  */
73588 
73589 /*
73590  * ToBoolean() (E5 Section 9.2)
73591  */
73592 
73593 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
73594  switch (DUK_TVAL_GET_TAG(tv)) {
73595  case DUK_TAG_UNDEFINED:
73596  case DUK_TAG_NULL:
73597  return 0;
73598  case DUK_TAG_BOOLEAN:
73599  DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
73600  return DUK_TVAL_GET_BOOLEAN(tv);
73601  case DUK_TAG_STRING: {
73602  /* Symbols ToBoolean() coerce to true, regardless of their
73603  * description. This happens with no explicit check because
73604  * of the symbol representation byte prefix.
73605  */
73606  duk_hstring *h = DUK_TVAL_GET_STRING(tv);
73607  DUK_ASSERT(h != NULL);
73608  return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
73609  }
73610  case DUK_TAG_OBJECT: {
73611  return 1;
73612  }
73613  case DUK_TAG_BUFFER: {
73614  /* Mimic Uint8Array semantics: objects coerce true, regardless
73615  * of buffer length (zero or not) or context.
73616  */
73617  return 1;
73618  }
73619  case DUK_TAG_POINTER: {
73620  void *p = DUK_TVAL_GET_POINTER(tv);
73621  return (p != NULL ? 1 : 0);
73622  }
73623  case DUK_TAG_LIGHTFUNC: {
73624  return 1;
73625  }
73626 #if defined(DUK_USE_FASTINT)
73627  case DUK_TAG_FASTINT:
73628  if (DUK_TVAL_GET_FASTINT(tv) != 0) {
73629  return 1;
73630  } else {
73631  return 0;
73632  }
73633 #endif
73634  default: {
73635  /* number */
73636  duk_double_t d;
73637 #if defined(DUK_USE_PREFER_SIZE)
73638  int c;
73639 #endif
73640  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
73641  DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
73642  d = DUK_TVAL_GET_DOUBLE(tv);
73643 #if defined(DUK_USE_PREFER_SIZE)
73644  c = DUK_FPCLASSIFY((double) d);
73645  if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
73646  return 0;
73647  } else {
73648  return 1;
73649  }
73650 #else
73651  DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
73652  return duk_double_is_nan_or_zero(d) ^ 1;
73653 #endif
73654  }
73655  }
73656  DUK_UNREACHABLE();
73657 }
73658 
73659 /*
73660  * ToNumber() (E5 Section 9.3)
73661  *
73662  * Value to convert must be on stack top, and is popped before exit.
73663  *
73664  * See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
73665  * http://www.cs.indiana.edu/~burger/fp/index.html
73666  *
73667  * Notes on the conversion:
73668  *
73669  * - There are specific requirements on the accuracy of the conversion
73670  * through a "Mathematical Value" (MV), so this conversion is not
73671  * trivial.
73672  *
73673  * - Quick rejects (e.g. based on first char) are difficult because
73674  * the grammar allows leading and trailing white space.
73675  *
73676  * - Quick reject based on string length is difficult even after
73677  * accounting for white space; there may be arbitrarily many
73678  * decimal digits.
73679  *
73680  * - Standard grammar allows decimal values ("123"), hex values
73681  * ("0x123") and infinities
73682  *
73683  * - Unlike source code literals, ToNumber() coerces empty strings
73684  * and strings with only whitespace to zero (not NaN).
73685  */
73686 
73687 /* E5 Section 9.3.1 */
73688 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
73689  duk_context *ctx = (duk_context *) thr;
73690  duk_small_uint_t s2n_flags;
73691  duk_double_t d;
73692 
73693  DUK_ASSERT(duk_is_string(ctx, -1));
73694 
73695  /* Quite lenient, e.g. allow empty as zero, but don't allow trailing
73696  * garbage.
73697  */
73698  s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
73699  DUK_S2N_FLAG_ALLOW_EXP |
73700  DUK_S2N_FLAG_ALLOW_PLUS |
73701  DUK_S2N_FLAG_ALLOW_MINUS |
73702  DUK_S2N_FLAG_ALLOW_INF |
73703  DUK_S2N_FLAG_ALLOW_FRAC |
73704  DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
73705  DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
73706  DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
73707  DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
73708  DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
73709  DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
73710  DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
73711 
73712  duk_numconv_parse(ctx, 10 /*radix*/, s2n_flags);
73713 
73714 #if defined(DUK_USE_PREFER_SIZE)
73715  d = duk_get_number(ctx, -1);
73716  duk_pop(ctx);
73717 #else
73718  thr->valstack_top--;
73719  DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
73720  DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top)); /* no fastint conversion in numconv now */
73721  DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
73722  d = DUK_TVAL_GET_DOUBLE(thr->valstack_top); /* assumes not a fastint */
73723  DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
73724 #endif
73725 
73726  return d;
73727 }
73728 
73729 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
73730  duk_context *ctx = (duk_hthread *) thr;
73731 
73732  DUK_ASSERT(thr != NULL);
73733  DUK_ASSERT(tv != NULL);
73734 
73735  switch (DUK_TVAL_GET_TAG(tv)) {
73736  case DUK_TAG_UNDEFINED: {
73737  /* return a specific NaN (although not strictly necessary) */
73738  duk_double_union du;
73739  DUK_DBLUNION_SET_NAN(&du);
73740  DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73741  return du.d;
73742  }
73743  case DUK_TAG_NULL: {
73744  /* +0.0 */
73745  return 0.0;
73746  }
73747  case DUK_TAG_BOOLEAN: {
73748  if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
73749  return 1.0;
73750  }
73751  return 0.0;
73752  }
73753  case DUK_TAG_STRING: {
73754  /* For Symbols ToNumber() is always a TypeError. */
73755  duk_hstring *h = DUK_TVAL_GET_STRING(tv);
73756  if (DUK_HSTRING_HAS_SYMBOL(h)) {
73757  DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
73758  }
73759  duk_push_hstring(ctx, h);
73760  return duk__tonumber_string_raw(thr);
73761  }
73762  case DUK_TAG_BUFFER: /* plain buffer treated like object */
73763  case DUK_TAG_OBJECT: {
73764  duk_double_t d;
73765  duk_push_tval(ctx, tv);
73766  duk_to_primitive(ctx, -1, DUK_HINT_NUMBER); /* 'tv' becomes invalid */
73767 
73768  /* recursive call for a primitive value (guaranteed not to cause second
73769  * recursion).
73770  */
73771  DUK_ASSERT(duk_get_tval(ctx, -1) != NULL);
73772  d = duk_js_tonumber(thr, duk_get_tval(ctx, -1));
73773 
73774  duk_pop(ctx);
73775  return d;
73776  }
73777  case DUK_TAG_POINTER: {
73778  /* Coerce like boolean */
73779  void *p = DUK_TVAL_GET_POINTER(tv);
73780  return (p != NULL ? 1.0 : 0.0);
73781  }
73782  case DUK_TAG_LIGHTFUNC: {
73783  /* +(function(){}) -> NaN */
73784  return DUK_DOUBLE_NAN;
73785  }
73786 #if defined(DUK_USE_FASTINT)
73787  case DUK_TAG_FASTINT:
73788  return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
73789 #endif
73790  default: {
73791  /* number */
73792  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
73793  DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
73794  return DUK_TVAL_GET_DOUBLE(tv);
73795  }
73796  }
73797 
73798  DUK_UNREACHABLE();
73799 }
73800 
73801 /*
73802  * ToInteger() (E5 Section 9.4)
73803  */
73804 
73805 /* exposed, used by e.g. duk_bi_date.c */
73806 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
73807 #if defined(DUK_USE_PREFER_SIZE)
73808  duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
73809 
73810  if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
73811  return 0.0;
73812  } else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
73813  return x;
73814  } else {
73815  /* Finite, including neg/pos zero. Neg zero sign must be
73816  * preserved.
73817  */
73818  return duk_double_trunc_towards_zero(x);
73819  }
73820 #else /* DUK_USE_PREFER_SIZE */
73821  /* NaN and Infinity have the same exponent so it's a cheap
73822  * initial check for the rare path.
73823  */
73824  if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x))) {
73825  if (duk_double_is_nan(x)) {
73826  return 0.0;
73827  } else {
73828  return x;
73829  }
73830  } else {
73831  return duk_double_trunc_towards_zero(x);
73832  }
73833 #endif /* DUK_USE_PREFER_SIZE */
73834 }
73835 
73836 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
73837  /* XXX: fastint */
73838  duk_double_t d = duk_js_tonumber(thr, tv); /* invalidates tv */
73839  return duk_js_tointeger_number(d);
73840 }
73841 
73842 /*
73843  * ToInt32(), ToUint32(), ToUint16() (E5 Sections 9.5, 9.6, 9.7)
73844  */
73845 
73846 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
73847 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
73848 #if defined (DUK_USE_PREFER_SIZE)
73849  duk_small_int_t c;
73850 #endif
73851 
73852 #if defined (DUK_USE_PREFER_SIZE)
73853  c = (duk_small_int_t) DUK_FPCLASSIFY(x);
73854  if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
73855  return 0.0;
73856  }
73857 #else
73858  if (duk_double_is_nan_zero_inf(x)) {
73859  return 0.0;
73860  }
73861 #endif
73862 
73863  /* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
73864  x = duk_double_trunc_towards_zero(x);
73865 
73866  /* NOTE: fmod(x) result sign is same as sign of x, which
73867  * differs from what Javascript wants (see Section 9.6).
73868  */
73869 
73870  x = DUK_FMOD(x, DUK_DOUBLE_2TO32); /* -> x in ]-2**32, 2**32[ */
73871 
73872  if (x < 0.0) {
73873  x += DUK_DOUBLE_2TO32;
73874  }
73875  DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32); /* -> x in [0, 2**32[ */
73876 
73877  if (is_toint32) {
73878  if (x >= DUK_DOUBLE_2TO31) {
73879  /* x in [2**31, 2**32[ */
73880 
73881  x -= DUK_DOUBLE_2TO32; /* -> x in [-2**31,2**31[ */
73882  }
73883  }
73884 
73885  return x;
73886 }
73887 
73888 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
73889  duk_double_t d;
73890 
73891 #if defined(DUK_USE_FASTINT)
73892  if (DUK_TVAL_IS_FASTINT(tv)) {
73893  return DUK_TVAL_GET_FASTINT_I32(tv);
73894  }
73895 #endif
73896 
73897  d = duk_js_tonumber(thr, tv); /* invalidates tv */
73898  d = duk__toint32_touint32_helper(d, 1);
73899  DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
73900  DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0); /* [-0x80000000,0x7fffffff] */
73901  DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d))); /* whole, won't clip */
73902  return (duk_int32_t) d;
73903 }
73904 
73905 
73906 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
73907  duk_double_t d;
73908 
73909 #if defined(DUK_USE_FASTINT)
73910  if (DUK_TVAL_IS_FASTINT(tv)) {
73911  return DUK_TVAL_GET_FASTINT_U32(tv);
73912  }
73913 #endif
73914 
73915  d = duk_js_tonumber(thr, tv); /* invalidates tv */
73916  d = duk__toint32_touint32_helper(d, 0);
73917  DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
73918  DUK_ASSERT(d >= 0.0 && d <= 4294967295.0); /* [0x00000000, 0xffffffff] */
73919  DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d))); /* whole, won't clip */
73920  return (duk_uint32_t) d;
73921 
73922 }
73923 
73924 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
73925  /* should be a safe way to compute this */
73926  return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
73927 }
73928 
73929 /*
73930  * ToString() (E5 Section 9.8)
73931  * ToObject() (E5 Section 9.9)
73932  * CheckObjectCoercible() (E5 Section 9.10)
73933  * IsCallable() (E5 Section 9.11)
73934  *
73935  * ==> implemented in the API.
73936  */
73937 
73938 /*
73939  * Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
73940  * 9.12). These have much in common so they can share some helpers.
73941  *
73942  * Future work notes:
73943  *
73944  * - Current implementation (and spec definition) has recursion; this should
73945  * be fixed if possible.
73946  *
73947  * - String-to-number coercion should be possible without going through the
73948  * value stack (and be more compact) if a shared helper is invoked.
73949  */
73950 
73951 /* Note that this is the same operation for strict and loose equality:
73952  * - E5 Section 11.9.3, step 1.c (loose)
73953  * - E5 Section 11.9.6, step 4 (strict)
73954  */
73955 
73956 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
73957 #if defined(DUK_USE_PARANOID_MATH)
73958  /* Straightforward algorithm, makes fewer compiler assumptions. */
73959  duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
73960  duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
73961  if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
73962  return 0;
73963  }
73964  if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
73965  return 1;
73966  }
73967  if (x == y) {
73968  return 1;
73969  }
73970  return 0;
73971 #else /* DUK_USE_PARANOID_MATH */
73972  /* Better equivalent algorithm. If the compiler is compliant, C and
73973  * Ecmascript semantics are identical for this particular comparison.
73974  * In particular, NaNs must never compare equal and zeroes must compare
73975  * equal regardless of sign. Could also use a macro, but this inlines
73976  * already nicely (no difference on gcc, for instance).
73977  */
73978  if (x == y) {
73979  /* IEEE requires that NaNs compare false */
73980  DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
73981  DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
73982  return 1;
73983  } else {
73984  /* IEEE requires that zeros compare the same regardless
73985  * of their signed, so if both x and y are zeroes, they
73986  * are caught above.
73987  */
73988  DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
73989  return 0;
73990  }
73991 #endif /* DUK_USE_PARANOID_MATH */
73992 }
73993 
73994 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
73995 #if defined(DUK_USE_PARANOID_MATH)
73996  duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
73997  duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
73998 
73999  if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
74000  /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
74001  return 1;
74002  }
74003  if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
74004  /* Note: cannot assume that a non-zero return value of signbit() would
74005  * always be the same -- hence cannot (portably) use something like:
74006  *
74007  * signbit(x) == signbit(y)
74008  */
74009  duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
74010  duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
74011  return (sx == sy);
74012  }
74013 
74014  /* normal comparison; known:
74015  * - both x and y are not NaNs (but one of them can be)
74016  * - both x and y are not zero (but one of them can be)
74017  * - x and y may be denormal or infinite
74018  */
74019 
74020  return (x == y);
74021 #else /* DUK_USE_PARANOID_MATH */
74022  duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
74023  duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
74024 
74025  if (x == y) {
74026  /* IEEE requires that NaNs compare false */
74027  DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
74028  DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
74029 
74030  /* Using classification has smaller footprint than direct comparison. */
74031  if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
74032  /* Note: cannot assume that a non-zero return value of signbit() would
74033  * always be the same -- hence cannot (portably) use something like:
74034  *
74035  * signbit(x) == signbit(y)
74036  */
74037  return duk_double_same_sign(x, y);
74038  }
74039  return 1;
74040  } else {
74041  /* IEEE requires that zeros compare the same regardless
74042  * of their sign, so if both x and y are zeroes, they
74043  * are caught above.
74044  */
74045  DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
74046 
74047  /* Difference to non-strict/strict comparison is that NaNs compare
74048  * equal and signed zero signs matter.
74049  */
74050  if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
74051  /* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
74052  return 1;
74053  }
74054  return 0;
74055  }
74056 #endif /* DUK_USE_PARANOID_MATH */
74057 }
74058 
74059 DUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
74060  duk_context *ctx = (duk_context *) thr;
74061  duk_uint_t type_mask_x;
74062  duk_uint_t type_mask_y;
74063 
74064  /* If flags != 0 (strict or SameValue), thr can be NULL. For loose
74065  * equals comparison it must be != NULL.
74066  */
74067  DUK_ASSERT(flags != 0 || thr != NULL);
74068 
74069  /*
74070  * Same type?
74071  *
74072  * Note: since number values have no explicit tag in the 8-byte
74073  * representation, need the awkward if + switch.
74074  */
74075 
74076 #if defined(DUK_USE_FASTINT)
74077  if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
74078  if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
74079  return 1;
74080  } else {
74081  return 0;
74082  }
74083  }
74084  else
74085 #endif
74086  if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
74087  duk_double_t d1, d2;
74088 
74089  /* Catches both doubles and cases where only one argument is
74090  * a fastint so can't assume a double.
74091  */
74092  d1 = DUK_TVAL_GET_NUMBER(tv_x);
74093  d2 = DUK_TVAL_GET_NUMBER(tv_y);
74094  if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
74095  /* SameValue */
74096  return duk__js_samevalue_number(d1, d2);
74097  } else {
74098  /* equals and strict equals */
74099  return duk__js_equals_number(d1, d2);
74100  }
74101  } else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
74102  switch (DUK_TVAL_GET_TAG(tv_x)) {
74103  case DUK_TAG_UNDEFINED:
74104  case DUK_TAG_NULL: {
74105  return 1;
74106  }
74107  case DUK_TAG_BOOLEAN: {
74108  return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
74109  }
74110  case DUK_TAG_POINTER: {
74111  return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
74112  }
74113  case DUK_TAG_STRING:
74114  case DUK_TAG_OBJECT: {
74115  /* Heap pointer comparison suffices for strings and objects.
74116  * Symbols compare equal if they have the same internal
74117  * representation; again heap pointer comparison suffices.
74118  */
74119  return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
74120  }
74121  case DUK_TAG_BUFFER: {
74122  /* In Duktape 2.x plain buffers mimic Uint8Array objects
74123  * so always compare by heap pointer. In Duktape 1.x
74124  * strict comparison would compare heap pointers and
74125  * non-strict would compare contents.
74126  */
74127  return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
74128  }
74129  case DUK_TAG_LIGHTFUNC: {
74130  /* At least 'magic' has a significant impact on function
74131  * identity.
74132  */
74133  duk_small_uint_t lf_flags_x;
74134  duk_small_uint_t lf_flags_y;
74135  duk_c_function func_x;
74136  duk_c_function func_y;
74137 
74138  DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
74139  DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
74140  return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
74141  }
74142 #if defined(DUK_USE_FASTINT)
74143  case DUK_TAG_FASTINT:
74144 #endif
74145  default: {
74146  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
74147  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
74148  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
74149  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
74150  DUK_UNREACHABLE();
74151  return 0;
74152  }
74153  }
74154  }
74155 
74156  if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
74157  return 0;
74158  }
74159 
74160  DUK_ASSERT(flags == 0); /* non-strict equality from here on */
74161 
74162  /*
74163  * Types are different; various cases for non-strict comparison
74164  *
74165  * Since comparison is symmetric, we use a "swap trick" to reduce
74166  * code size.
74167  */
74168 
74169  type_mask_x = duk_get_type_mask_tval(tv_x);
74170  type_mask_y = duk_get_type_mask_tval(tv_y);
74171 
74172  /* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
74173  if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
74174  (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
74175  return 1;
74176  }
74177 
74178  /* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
74179  if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
74180  if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
74181  duk_double_t d1, d2;
74182  d1 = DUK_TVAL_GET_NUMBER(tv_x);
74183  d2 = duk_to_number_tval(ctx, tv_y);
74184  return duk__js_equals_number(d1, d2);
74185  }
74186  }
74187  if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
74188  if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
74189  duk_double_t d1, d2;
74190  d1 = DUK_TVAL_GET_NUMBER(tv_y);
74191  d2 = duk_to_number_tval(ctx, tv_x);
74192  return duk__js_equals_number(d1, d2);
74193  }
74194  }
74195 
74196  /* Boolean/any -> coerce boolean to number and try again. If boolean is
74197  * compared to a pointer, the final comparison after coercion now always
74198  * yields false (as pointer vs. number compares to false), but this is
74199  * not special cased.
74200  *
74201  * ToNumber(bool) is +1.0 or 0.0. Tagged boolean value is always 0 or 1.
74202  */
74203  if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
74204  DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
74205  duk_push_int(ctx, DUK_TVAL_GET_BOOLEAN(tv_x));
74206  duk_push_tval(ctx, tv_y);
74207  goto recursive_call;
74208  }
74209  if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
74210  DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
74211  duk_push_tval(ctx, tv_x);
74212  duk_push_int(ctx, DUK_TVAL_GET_BOOLEAN(tv_y));
74213  goto recursive_call;
74214  }
74215 
74216  /* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
74217  if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
74218  (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
74219  /* No symbol check needed because symbols and strings are accepted. */
74220  duk_push_tval(ctx, tv_x);
74221  duk_push_tval(ctx, tv_y);
74222  duk_to_primitive(ctx, -1, DUK_HINT_NONE); /* apparently no hint? */
74223  goto recursive_call;
74224  }
74225  if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
74226  (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
74227  /* No symbol check needed because symbols and strings are accepted. */
74228  duk_push_tval(ctx, tv_x);
74229  duk_push_tval(ctx, tv_y);
74230  duk_to_primitive(ctx, -2, DUK_HINT_NONE); /* apparently no hint? */
74231  goto recursive_call;
74232  }
74233 
74234  /* Nothing worked -> not equal. */
74235  return 0;
74236 
74237  recursive_call:
74238  /* Shared code path to call the helper again with arguments on stack top. */
74239  {
74240  duk_bool_t rc;
74241  rc = duk_js_equals_helper(thr,
74242  DUK_GET_TVAL_NEGIDX(ctx, -2),
74243  DUK_GET_TVAL_NEGIDX(ctx, -1),
74244  0 /*flags:nonstrict*/);
74245  duk_pop_2(ctx);
74246  return rc;
74247  }
74248 }
74249 
74250 /*
74251  * Comparisons (x >= y, x > y, x <= y, x < y)
74252  *
74253  * E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
74254  * flags to get the rest.
74255  */
74256 
74257 /* XXX: this should probably just operate on the stack top, because it
74258  * needs to push stuff on the stack anyway...
74259  */
74260 
74261 DUK_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) {
74262  duk_size_t prefix_len;
74263  duk_small_int_t rc;
74264 
74265  prefix_len = (len1 <= len2 ? len1 : len2);
74266 
74267  /* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length
74268  * inputs so no zero length check is needed.
74269  */
74270  rc = DUK_MEMCMP((const void *) buf1,
74271  (const void *) buf2,
74272  (size_t) prefix_len);
74273 
74274  if (rc < 0) {
74275  return -1;
74276  } else if (rc > 0) {
74277  return 1;
74278  }
74279 
74280  /* prefix matches, lengths matter now */
74281  if (len1 < len2) {
74282  /* e.g. "x" < "xx" */
74283  return -1;
74284  } else if (len1 > len2) {
74285  return 1;
74286  }
74287 
74288  return 0;
74289 }
74290 
74291 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
74292  /*
74293  * String comparison (E5 Section 11.8.5, step 4), which
74294  * needs to compare codepoint by codepoint.
74295  *
74296  * However, UTF-8 allows us to use strcmp directly: the shared
74297  * prefix will be encoded identically (UTF-8 has unique encoding)
74298  * and the first differing character can be compared with a simple
74299  * unsigned byte comparison (which strcmp does).
74300  *
74301  * This will not work properly for non-xutf-8 strings, but this
74302  * is not an issue for compliance.
74303  */
74304 
74305  DUK_ASSERT(h1 != NULL);
74306  DUK_ASSERT(h2 != NULL);
74307 
74308  return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
74309  (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
74310  (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
74311  (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
74312 }
74313 
74314 #if 0 /* unused */
74315 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
74316  /* Similar to String comparison. */
74317 
74318  DUK_ASSERT(h1 != NULL);
74319  DUK_ASSERT(h2 != NULL);
74320  DUK_UNREF(heap);
74321 
74322  return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
74323  (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
74324  (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
74325  (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
74326 }
74327 #endif
74328 
74329 #if defined(DUK_USE_FASTINT)
74330 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
74331  DUK_ASSERT(retval == 0 || retval == 1);
74332  if (v1 < v2) {
74333  return retval ^ 1;
74334  } else {
74335  return retval;
74336  }
74337 }
74338 #endif
74339 
74340 #if defined(DUK_USE_PARANOID_MATH)
74341 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
74342  duk_small_int_t c1, s1, c2, s2;
74343 
74344  DUK_ASSERT(retval == 0 || retval == 1);
74345  c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
74346  s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
74347  c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
74348  s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
74349 
74350  if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
74351  return 0; /* Always false, regardless of negation. */
74352  }
74353 
74354  if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
74355  /* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
74356  * steps e, f, and g.
74357  */
74358  return retval; /* false */
74359  }
74360 
74361  if (d1 == d2) {
74362  return retval; /* false */
74363  }
74364 
74365  if (c1 == DUK_FP_INFINITE && s1 == 0) {
74366  /* x == +Infinity */
74367  return retval; /* false */
74368  }
74369 
74370  if (c2 == DUK_FP_INFINITE && s2 == 0) {
74371  /* y == +Infinity */
74372  return retval ^ 1; /* true */
74373  }
74374 
74375  if (c2 == DUK_FP_INFINITE && s2 != 0) {
74376  /* y == -Infinity */
74377  return retval; /* false */
74378  }
74379 
74380  if (c1 == DUK_FP_INFINITE && s1 != 0) {
74381  /* x == -Infinity */
74382  return retval ^ 1; /* true */
74383  }
74384 
74385  if (d1 < d2) {
74386  return retval ^ 1; /* true */
74387  }
74388 
74389  return retval; /* false */
74390 }
74391 #else /* DUK_USE_PARANOID_MATH */
74392 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
74393  /* This comparison tree relies doesn't match the exact steps in
74394  * E5 Section 11.8.5 but should produce the same results. The
74395  * steps rely on exact IEEE semantics for NaNs, etc.
74396  */
74397 
74398  DUK_ASSERT(retval == 0 || retval == 1);
74399  if (d1 < d2) {
74400  /* In no case should both (d1 < d2) and (d2 < d1) be true.
74401  * It's possible that neither is true though, and that's
74402  * handled below.
74403  */
74404  DUK_ASSERT(!(d2 < d1));
74405 
74406  /* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
74407  * - d2 is +Infinity, d1 != +Infinity and NaN
74408  * - d1 is -Infinity, d2 != -Infinity and NaN
74409  */
74410  return retval ^ 1;
74411  } else {
74412  if (d2 < d1) {
74413  /* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
74414  * - d1 is +Infinity, d2 != +Infinity and NaN
74415  * - d2 is -Infinity, d1 != -Infinity and NaN
74416  */
74417  return retval;
74418  } else {
74419  /* - d1 and/or d2 is NaN
74420  * - d1 and d2 are both +/- 0
74421  * - d1 == d2 (including infinities)
74422  */
74423  if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
74424  /* Note: undefined from Section 11.8.5 always
74425  * results in false return (see e.g. Section
74426  * 11.8.3) - hence special treatment here.
74427  */
74428  return 0; /* zero regardless of negation */
74429  } else {
74430  return retval;
74431  }
74432  }
74433  }
74434 }
74435 #endif /* DUK_USE_PARANOID_MATH */
74436 
74437 DUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_int_t flags) {
74438  duk_context *ctx = (duk_context *) thr;
74439  duk_double_t d1, d2;
74440  duk_small_int_t rc;
74441  duk_bool_t retval;
74442 
74443  DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1); /* Rely on this flag being lowest. */
74444  retval = flags & DUK_COMPARE_FLAG_NEGATE;
74445  DUK_ASSERT(retval == 0 || retval == 1);
74446 
74447  /* Fast path for fastints */
74448 #if defined(DUK_USE_FASTINT)
74449  if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
74450  return duk__compare_fastint(retval,
74451  DUK_TVAL_GET_FASTINT(tv_x),
74452  DUK_TVAL_GET_FASTINT(tv_y));
74453  }
74454 #endif /* DUK_USE_FASTINT */
74455 
74456  /* Fast path for numbers (one of which may be a fastint) */
74457 #if !defined(DUK_USE_PREFER_SIZE)
74458  if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
74459  return duk__compare_number(retval,
74460  DUK_TVAL_GET_NUMBER(tv_x),
74461  DUK_TVAL_GET_NUMBER(tv_y));
74462  }
74463 #endif
74464 
74465  /* Slow path */
74466 
74467  duk_push_tval(ctx, tv_x);
74468  duk_push_tval(ctx, tv_y);
74469 
74470  if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
74471  duk_to_primitive(ctx, -2, DUK_HINT_NUMBER);
74472  duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
74473  } else {
74474  duk_to_primitive(ctx, -1, DUK_HINT_NUMBER);
74475  duk_to_primitive(ctx, -2, DUK_HINT_NUMBER);
74476  }
74477 
74478  /* Note: reuse variables */
74479  tv_x = DUK_GET_TVAL_NEGIDX(ctx, -2);
74480  tv_y = DUK_GET_TVAL_NEGIDX(ctx, -1);
74481 
74482  if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
74483  duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
74484  duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
74485  DUK_ASSERT(h1 != NULL);
74486  DUK_ASSERT(h2 != NULL);
74487 
74488  if (!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2)) {
74489  rc = duk_js_string_compare(h1, h2);
74490  duk_pop_2(ctx);
74491  if (rc < 0) {
74492  return retval ^ 1;
74493  } else {
74494  return retval;
74495  }
74496  }
74497 
74498  /* One or both are Symbols: fall through to handle in the
74499  * generic path. Concretely, ToNumber() will fail.
74500  */
74501  }
74502 
74503  /* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
74504 #if 0
74505  if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
74506  d1 = duk_to_number_m2(ctx);
74507  d2 = duk_to_number_m1(ctx);
74508  } else {
74509  d2 = duk_to_number_m1(ctx);
74510  d1 = duk_to_number_m2(ctx);
74511  }
74512 #endif
74513  d1 = duk_to_number_m2(ctx);
74514  d2 = duk_to_number_m1(ctx);
74515 
74516  /* We want to duk_pop_2(ctx); because the values are numbers
74517  * no decref check is needed.
74518  */
74519 #if defined(DUK_USE_PREFER_SIZE)
74520  duk_pop_2(ctx);
74521 #else
74522  DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(ctx, -2)));
74523  DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(ctx, -1)));
74524  DUK_ASSERT(duk_get_top(ctx) >= 2);
74525  ((duk_hthread *) ctx)->valstack_top -= 2;
74526  tv_x = ((duk_hthread *) ctx)->valstack_top;
74527  tv_y = tv_x + 1;
74528  DUK_TVAL_SET_UNDEFINED(tv_x); /* Value stack policy */
74529  DUK_TVAL_SET_UNDEFINED(tv_y);
74530 #endif
74531 
74532  return duk__compare_number(retval, d1, d2);
74533 }
74534 
74535 /*
74536  * instanceof
74537  */
74538 
74539 /*
74540  * E5 Section 11.8.6 describes the main algorithm, which uses
74541  * [[HasInstance]]. [[HasInstance]] is defined for only
74542  * function objects:
74543  *
74544  * - Normal functions:
74545  * E5 Section 15.3.5.3
74546  * - Functions established with Function.prototype.bind():
74547  * E5 Section 15.3.4.5.3
74548  *
74549  * For other objects, a TypeError is thrown.
74550  *
74551  * Limited Proxy support: don't support 'getPrototypeOf' trap but
74552  * continue lookup in Proxy target if the value is a Proxy.
74553  */
74554 
74555 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
74556  duk_context *ctx = (duk_context *) thr;
74557  duk_hobject *func;
74558  duk_hobject *val;
74559  duk_hobject *proto;
74560  duk_tval *tv;
74561  duk_uint_t sanity;
74562  duk_bool_t skip_first;
74563 
74564  /*
74565  * Get the values onto the stack first. It would be possible to cover
74566  * some normal cases without resorting to the value stack.
74567  *
74568  * The right hand side could be a light function (as they generally
74569  * behave like objects). Light functions never have a 'prototype'
74570  * property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
74571  * Using duk_require_hobject() is thus correct (except for error msg).
74572  */
74573 
74574  duk_push_tval(ctx, tv_x);
74575  duk_push_tval(ctx, tv_y);
74576  func = duk_require_hobject(ctx, -1);
74577 
74578  /*
74579  * For bound objects, [[HasInstance]] just calls the target function
74580  * [[HasInstance]]. If that is again a bound object, repeat until
74581  * we find a non-bound Function object.
74582  */
74583 
74584  /* XXX: this bound function resolution also happens elsewhere,
74585  * move into a shared helper.
74586  */
74587 
74588  sanity = DUK_HOBJECT_BOUND_CHAIN_SANITY;
74589  do {
74590  /* check func supports [[HasInstance]] (this is checked for every function
74591  * in the bound chain, including the final one)
74592  */
74593 
74594  if (!DUK_HOBJECT_IS_CALLABLE(func)) {
74595  /*
74596  * Note: of native Ecmascript objects, only Function instances
74597  * have a [[HasInstance]] internal property. Custom objects might
74598  * also have it, but not in current implementation.
74599  *
74600  * XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
74601  */
74602  DUK_ERROR_TYPE(thr, "invalid instanceof rval");
74603  }
74604 
74605  if (!DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
74606  break;
74607  }
74608 
74609  /* [ ... lval rval ] */
74610 
74611  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_TARGET); /* -> [ ... lval rval new_rval ] */
74612  duk_replace(ctx, -1); /* -> [ ... lval new_rval ] */
74613  func = duk_require_hobject(ctx, -1);
74614 
74615  /* func support for [[HasInstance]] checked in the beginning of the loop */
74616  } while (--sanity > 0);
74617 
74618  if (sanity == 0) {
74619  DUK_ERROR_RANGE(thr, DUK_STR_BOUND_CHAIN_LIMIT);
74620  }
74621 
74622  /*
74623  * 'func' is now a non-bound object which supports [[HasInstance]]
74624  * (which here just means DUK_HOBJECT_FLAG_CALLABLE). Move on
74625  * to execute E5 Section 15.3.5.3.
74626  */
74627 
74628  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
74629  DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
74630 
74631  /* [ ... lval rval(func) ] */
74632 
74633  /* For lightfuncs, buffers, and pointers start the comparison directly
74634  * from the virtual prototype object.
74635  */
74636  skip_first = 0;
74637  tv = DUK_GET_TVAL_NEGIDX(ctx, -2);
74638  switch (DUK_TVAL_GET_TAG(tv)) {
74639  case DUK_TAG_LIGHTFUNC:
74640  val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
74641  DUK_ASSERT(val != NULL);
74642  break;
74643  case DUK_TAG_BUFFER:
74644  val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
74645  DUK_ASSERT(val != NULL);
74646  break;
74647  case DUK_TAG_POINTER:
74648  val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
74649  DUK_ASSERT(val != NULL);
74650  break;
74651  case DUK_TAG_OBJECT:
74652  skip_first = 1; /* Ignore object itself on first round. */
74653  val = DUK_TVAL_GET_OBJECT(tv);
74654  DUK_ASSERT(val != NULL);
74655  break;
74656  default:
74657  goto pop_and_false;
74658  }
74659  DUK_ASSERT(val != NULL); /* Loop doesn't actually rely on this. */
74660 
74661  duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_PROTOTYPE); /* -> [ ... lval rval rval.prototype ] */
74662  proto = duk_require_hobject(ctx, -1);
74663  duk_pop(ctx); /* -> [ ... lval rval ] */
74664 
74665  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
74666  do {
74667  /*
74668  * Note: prototype chain is followed BEFORE first comparison. This
74669  * means that the instanceof lval is never itself compared to the
74670  * rval.prototype property. This is apparently intentional, see E5
74671  * Section 15.3.5.3, step 4.a.
74672  *
74673  * Also note:
74674  *
74675  * js> (function() {}) instanceof Function
74676  * true
74677  * js> Function instanceof Function
74678  * true
74679  *
74680  * For the latter, h_proto will be Function.prototype, which is the
74681  * built-in Function prototype. Because Function.[[Prototype]] is
74682  * also the built-in Function prototype, the result is true.
74683  */
74684 
74685  if (!val) {
74686  goto pop_and_false;
74687  }
74688 
74689  DUK_ASSERT(val != NULL);
74690 #if defined(DUK_USE_ES6_PROXY)
74691  val = duk_hobject_resolve_proxy_target(thr, val);
74692 #endif
74693 
74694  if (skip_first) {
74695  skip_first = 0;
74696  } else if (val == proto) {
74697  goto pop_and_true;
74698  }
74699 
74700  DUK_ASSERT(val != NULL);
74701  val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
74702  } while (--sanity > 0);
74703 
74704  if (sanity == 0) {
74705  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
74706  }
74707  DUK_UNREACHABLE();
74708 
74709  pop_and_false:
74710  duk_pop_2(ctx);
74711  return 0;
74712 
74713  pop_and_true:
74714  duk_pop_2(ctx);
74715  return 1;
74716 }
74717 
74718 /*
74719  * in
74720  */
74721 
74722 /*
74723  * E5 Sections 11.8.7, 8.12.6.
74724  *
74725  * Basically just a property existence check using [[HasProperty]].
74726  */
74727 
74728 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
74729  duk_context *ctx = (duk_context *) thr;
74730  duk_bool_t retval;
74731 
74732  /*
74733  * Get the values onto the stack first. It would be possible to cover
74734  * some normal cases without resorting to the value stack (e.g. if
74735  * lval is already a string).
74736  */
74737 
74738  /* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
74739  * must be string coerced before the internal HasProperty() algorithm is
74740  * invoked. A fast path skipping coercion could be safely implemented for
74741  * numbers (as number-to-string coercion has no side effects). For ES2015
74742  * proxy behavior, the trap 'key' argument must be in a string coerced
74743  * form (which is a shame).
74744  */
74745 
74746  /* TypeError if rval is not an object or object like (e.g. lightfunc
74747  * or plain buffer).
74748  */
74749  duk_push_tval(ctx, tv_x);
74750  duk_push_tval(ctx, tv_y);
74751  duk_require_type_mask(ctx, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
74752 
74753  (void) duk_to_property_key_hstring(ctx, -2);
74754 
74755  retval = duk_hobject_hasprop(thr,
74756  DUK_GET_TVAL_NEGIDX(ctx, -1),
74757  DUK_GET_TVAL_NEGIDX(ctx, -2));
74758 
74759  duk_pop_2(ctx);
74760  return retval;
74761 }
74762 
74763 /*
74764  * typeof
74765  *
74766  * E5 Section 11.4.3.
74767  *
74768  * Very straightforward. The only question is what to return for our
74769  * non-standard tag / object types.
74770  *
74771  * There is an unfortunate string constant define naming problem with
74772  * typeof return values for e.g. "Object" and "object"; careful with
74773  * the built-in string defines. The LC_XXX defines are used for the
74774  * lowercase variants now.
74775  */
74776 
74777 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
74778  duk_small_uint_t stridx = 0;
74779 
74780  switch (DUK_TVAL_GET_TAG(tv_x)) {
74781  case DUK_TAG_UNDEFINED: {
74782  stridx = DUK_STRIDX_LC_UNDEFINED;
74783  break;
74784  }
74785  case DUK_TAG_NULL: {
74786  /* Note: not a typo, "object" is returned for a null value. */
74787  stridx = DUK_STRIDX_LC_OBJECT;
74788  break;
74789  }
74790  case DUK_TAG_BOOLEAN: {
74791  stridx = DUK_STRIDX_LC_BOOLEAN;
74792  break;
74793  }
74794  case DUK_TAG_POINTER: {
74795  /* Implementation specific. */
74796  stridx = DUK_STRIDX_LC_POINTER;
74797  break;
74798  }
74799  case DUK_TAG_STRING: {
74800  duk_hstring *str;
74801 
74802  /* All internal keys are identified as Symbols. */
74803  str = DUK_TVAL_GET_STRING(tv_x);
74804  DUK_ASSERT(str != NULL);
74805  if (DUK_HSTRING_HAS_SYMBOL(str)) {
74806  stridx = DUK_STRIDX_LC_SYMBOL;
74807  } else {
74808  stridx = DUK_STRIDX_LC_STRING;
74809  }
74810  break;
74811  }
74812  case DUK_TAG_OBJECT: {
74813  duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
74814  DUK_ASSERT(obj != NULL);
74815  if (DUK_HOBJECT_IS_CALLABLE(obj)) {
74816  stridx = DUK_STRIDX_LC_FUNCTION;
74817  } else {
74818  stridx = DUK_STRIDX_LC_OBJECT;
74819  }
74820  break;
74821  }
74822  case DUK_TAG_BUFFER: {
74823  /* Implementation specific. In Duktape 1.x this would be
74824  * 'buffer', in Duktape 2.x changed to 'object' because plain
74825  * buffers now mimic Uint8Array objects.
74826  */
74827  stridx = DUK_STRIDX_LC_OBJECT;
74828  break;
74829  }
74830  case DUK_TAG_LIGHTFUNC: {
74831  stridx = DUK_STRIDX_LC_FUNCTION;
74832  break;
74833  }
74834 #if defined(DUK_USE_FASTINT)
74835  case DUK_TAG_FASTINT:
74836 #endif
74837  default: {
74838  /* number */
74839  DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
74840  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
74841  stridx = DUK_STRIDX_LC_NUMBER;
74842  break;
74843  }
74844  }
74845 
74846  DUK_ASSERT_STRIDX_VALID(stridx);
74847  return stridx;
74848 }
74849 
74850 /*
74851  * Array index and length
74852  *
74853  * Array index: E5 Section 15.4
74854  * Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
74855  *
74856  * duk_js_to_arrayindex_string_helper() computes the array index from
74857  * string contents alone. Depending on options it's only called during
74858  * string intern (and value stored to duk_hstring) or it's called also
74859  * at runtime.
74860  */
74861 
74862 DUK_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) {
74863  duk_uarridx_t res, new_res;
74864 
74865  if (blen == 0 || blen > 10) {
74866  goto parse_fail;
74867  }
74868  if (str[0] == (duk_uint8_t) '0' && blen > 1) {
74869  goto parse_fail;
74870  }
74871 
74872  /* Accept 32-bit decimal integers, no leading zeroes, signs, etc.
74873  * Leading zeroes are not accepted (zero index "0" is an exception
74874  * handled above).
74875  */
74876 
74877  res = 0;
74878  while (blen-- > 0) {
74879  duk_uint8_t c = *str++;
74880  if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
74881  new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
74882  if (new_res < res) {
74883  /* overflow, more than 32 bits -> not an array index */
74884  goto parse_fail;
74885  }
74886  res = new_res;
74887  } else {
74888  goto parse_fail;
74889  }
74890  }
74891 
74892  *out_idx = res;
74893  return 1;
74894 
74895  parse_fail:
74896  *out_idx = DUK_HSTRING_NO_ARRAY_INDEX;
74897  return 0;
74898 }
74899 
74900 /* Called by duk_hstring.h macros */
74901 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) {
74902  duk_uarridx_t res;
74903  duk_small_int_t rc;
74904 
74905  if (!DUK_HSTRING_HAS_ARRIDX(h)) {
74906  return DUK_HSTRING_NO_ARRAY_INDEX;
74907  }
74908 
74909  rc = duk_js_to_arrayindex_raw_string(DUK_HSTRING_GET_DATA(h),
74910  DUK_HSTRING_GET_BYTELEN(h),
74911  &res);
74912  DUK_UNREF(rc);
74913  DUK_ASSERT(rc != 0);
74914  return res;
74915 }
74916 /*
74917  * Identifier access and function closure handling.
74918  *
74919  * Provides the primitives for slow path identifier accesses: GETVAR,
74920  * PUTVAR, DELVAR, etc. The fast path, direct register accesses, should
74921  * be used for most identifier accesses. Consequently, these slow path
74922  * primitives should be optimized for maximum compactness.
74923  *
74924  * Ecmascript environment records (declarative and object) are represented
74925  * as internal objects with control keys. Environment records have a
74926  * parent record ("outer environment reference") which is represented by
74927  * the implicit prototype for technical reasons (in other words, it is a
74928  * convenient field). The prototype chain is not followed in the ordinary
74929  * sense for variable lookups.
74930  *
74931  * See identifier-handling.rst for more details on the identifier algorithms
74932  * and the internal representation. See function-objects.rst for details on
74933  * what function templates and instances are expected to look like.
74934  *
74935  * Care must be taken to avoid duk_tval pointer invalidation caused by
74936  * e.g. value stack or object resizing.
74937  *
74938  * TODO: properties for function instances could be initialized much more
74939  * efficiently by creating a property allocation for a certain size and
74940  * filling in keys and values directly (and INCREFing both with "bulk incref"
74941  * primitives.
74942  *
74943  * XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
74944  * awkward (especially because they follow the prototype chain); rework
74945  * if "raw" own property helpers are added.
74946  */
74947 
74948 /* #include duk_internal.h -> already included */
74949 
74950 /*
74951  * Local result type for duk__get_identifier_reference() lookup.
74952  */
74953 
74954 typedef struct {
74955  duk_hobject *holder; /* for object-bound identifiers */
74956  duk_tval *value; /* for register-bound and declarative env identifiers */
74957  duk_int_t attrs; /* property attributes for identifier (relevant if value != NULL) */
74958  duk_tval *this_binding;
74959  duk_hobject *env;
74961 
74962 /*
74963  * Create a new function object based on a "template function" which contains
74964  * compiled bytecode, constants, etc, but lacks a lexical environment.
74965  *
74966  * Ecmascript requires that each created closure is a separate object, with
74967  * its own set of editable properties. However, structured property values
74968  * (such as the formal arguments list and the variable map) are shared.
74969  * Also the bytecode, constants, and inner functions are shared.
74970  *
74971  * See E5 Section 13.2 for detailed requirements on the function objects;
74972  * there are no similar requirements for function "templates" which are an
74973  * implementation dependent internal feature. Also see function-objects.rst
74974  * for a discussion on the function instance properties provided by this
74975  * implementation.
74976  *
74977  * Notes:
74978  *
74979  * * Order of internal properties should match frequency of use, since the
74980  * properties will be linearly scanned on lookup (functions usually don't
74981  * have enough properties to warrant a hash part).
74982  *
74983  * * The created closure is independent of its template; they do share the
74984  * same 'data' buffer object, but the template object itself can be freed
74985  * even if the closure object remains reachable.
74986  */
74987 
74988 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
74989  duk_tval *tv, *tv_end;
74990  duk_hobject **funcs, **funcs_end;
74991 
74992  DUK_UNREF(thr);
74993 
74994  /* If function creation fails due to out-of-memory, the data buffer
74995  * pointer may be NULL in some cases. That's actually possible for
74996  * GC code, but shouldn't be possible here because the incomplete
74997  * function will be unwound from the value stack and never instantiated.
74998  */
74999  DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
75000 
75001  tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
75002  tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
75003  while (tv < tv_end) {
75004  DUK_TVAL_INCREF(thr, tv);
75005  tv++;
75006  }
75007 
75008  funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
75009  funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
75010  while (funcs < funcs_end) {
75011  DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
75012  funcs++;
75013  }
75014 }
75015 
75016 /* Push a new closure on the stack.
75017  *
75018  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
75019  * is created when the function is called, only outer_lex_env matters
75020  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
75021  */
75022 
75023 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
75024  /* order: most frequent to least frequent */
75025  DUK_STRIDX_INT_VARMAP,
75026  DUK_STRIDX_INT_FORMALS,
75027 #if defined(DUK_USE_PC2LINE)
75028  DUK_STRIDX_INT_PC2LINE,
75029 #endif
75030 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
75031  DUK_STRIDX_FILE_NAME,
75032 #endif
75033 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
75034  DUK_STRIDX_INT_SOURCE
75035 #endif
75036 };
75037 
75038 DUK_INTERNAL
75039 void duk_js_push_closure(duk_hthread *thr,
75040  duk_hcompfunc *fun_temp,
75041  duk_hobject *outer_var_env,
75042  duk_hobject *outer_lex_env,
75043  duk_bool_t add_auto_proto) {
75044  duk_context *ctx = (duk_context *) thr;
75045  duk_hcompfunc *fun_clos;
75046  duk_small_uint_t i;
75047  duk_uint_t len_value;
75048 
75049  DUK_ASSERT(fun_temp != NULL);
75050  DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
75051  DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
75052  DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
75053  DUK_ASSERT(outer_var_env != NULL);
75054  DUK_ASSERT(outer_lex_env != NULL);
75055  DUK_UNREF(len_value);
75056 
75057  fun_clos = duk_push_hcompfunc(ctx);
75058  DUK_ASSERT(fun_clos != NULL);
75059  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
75060 
75061  duk_push_hobject(ctx, &fun_temp->obj); /* -> [ ... closure template ] */
75062 
75063  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
75064  DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
75065  DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
75066  DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
75067 
75068  DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
75069  DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
75070  DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
75071 
75072  /* Note: all references inside 'data' need to get their refcounts
75073  * upped too. This is the case because refcounts are decreased
75074  * through every function referencing 'data' independently.
75075  */
75076 
75077  DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
75078  duk__inc_data_inner_refcounts(thr, fun_temp);
75079 
75080  fun_clos->nregs = fun_temp->nregs;
75081  fun_clos->nargs = fun_temp->nargs;
75082 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75083  fun_clos->start_line = fun_temp->start_line;
75084  fun_clos->end_line = fun_temp->end_line;
75085 #endif
75086 
75087  DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
75088  DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
75089  DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
75090 
75091  /* XXX: could also copy from template, but there's no way to have any
75092  * other value here now (used code has no access to the template).
75093  */
75094  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
75095 
75096  /* Copy duk_hobject flags as is from the template using a mask.
75097  * Leave out duk_heaphdr owned flags just in case (e.g. if there's
75098  * some GC flag or similar). Some flags can then be adjusted
75099  * separately if necessary.
75100  */
75101 
75102  /* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
75103  DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
75104  DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
75105  (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
75106  (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
75107 
75108  DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
75109  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
75110  DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
75111  DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
75112  DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(&fun_clos->obj));
75113  /* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
75114  /* DUK_HOBJECT_FLAG_NEWENV: handled below */
75115  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
75116  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
75117  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
75118 
75119  if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
75120  /* If the template is not constructable don't add an automatic
75121  * .prototype property. This is the case for e.g. ES2015 object
75122  * literal getters/setters and method definitions.
75123  */
75124  add_auto_proto = 0;
75125  }
75126 
75127  /*
75128  * Setup environment record properties based on the template and
75129  * its flags.
75130  *
75131  * If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
75132  * records represent identifiers "outside" the function; the
75133  * "inner" environment records are created on demand. Otherwise,
75134  * the environment records are those that will be directly used
75135  * (e.g. for declarations).
75136  *
75137  * _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
75138  * so _Varenv is only set if _Lexenv != _Varenv.
75139  *
75140  * This is relatively complex, see doc/identifier-handling.rst.
75141  */
75142 
75143  if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
75144 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
75145  if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
75146  duk_hobject *proto;
75147  duk_hobject *new_env;
75148 
75149  /*
75150  * Named function expression, name needs to be bound
75151  * in an intermediate environment record. The "outer"
75152  * lexical/variable environment will thus be:
75153  *
75154  * a) { funcname: <func>, __prototype: outer_lex_env }
75155  * b) { funcname: <func>, __prototype: <globalenv> } (if outer_lex_env missing)
75156  */
75157 
75158  if (outer_lex_env) {
75159  proto = outer_lex_env;
75160  } else {
75161  proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
75162  }
75163 
75164  /* -> [ ... closure template env ] */
75165  new_env = duk_push_object_helper_proto(ctx,
75166  DUK_HOBJECT_FLAG_EXTENSIBLE |
75167  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
75168  proto);
75169  DUK_ASSERT(new_env != NULL);
75170 
75171  /* It's important that duk_xdef_prop() is a 'raw define' so that any
75172  * properties in an ancestor are never an issue (they should never be
75173  * e.g. non-writable, but just in case).
75174  *
75175  * Because template objects are not visible to user code, the case
75176  * where .name is missing shouldn't happen in practice. It it does,
75177  * the name 'undefined' gets bound and maps to the closure (which is
75178  * a bit odd, but safe).
75179  */
75180  (void) duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_NAME);
75181  /* -> [ ... closure template env funcname ] */
75182  duk_dup_m4(ctx); /* -> [ ... closure template env funcname closure ] */
75183  duk_xdef_prop(ctx, -3, DUK_PROPDESC_FLAGS_NONE); /* -> [ ... closure template env ] */
75184  /* env[funcname] = closure */
75185 
75186  /* [ ... closure template env ] */
75187 
75188  DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, new_env);
75189  DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, new_env);
75190  DUK_HOBJECT_INCREF(thr, new_env);
75191  DUK_HOBJECT_INCREF(thr, new_env);
75192  duk_pop(ctx);
75193 
75194  /* [ ... closure template ] */
75195  }
75196  else
75197 #endif /* DUK_USE_FUNC_NAME_PROPERTY */
75198  {
75199  /*
75200  * Other cases (function declaration, anonymous function expression,
75201  * strict direct eval code). The "outer" environment will be whatever
75202  * the caller gave us.
75203  */
75204 
75205  DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
75206  DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
75207  DUK_HOBJECT_INCREF(thr, outer_lex_env);
75208  DUK_HOBJECT_INCREF(thr, outer_lex_env);
75209 
75210  /* [ ... closure template ] */
75211  }
75212  } else {
75213  /*
75214  * Function gets no new environment when called. This is the
75215  * case for global code, indirect eval code, and non-strict
75216  * direct eval code. There is no direct correspondence to the
75217  * E5 specification, as global/eval code is not exposed as a
75218  * function.
75219  */
75220 
75221  DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
75222 
75223  DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
75224  DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
75225  DUK_HOBJECT_INCREF(thr, outer_lex_env); /* NULLs not allowed; asserted on entry */
75226  DUK_HOBJECT_INCREF(thr, outer_var_env);
75227  }
75228  DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
75229  (duk_heaphdr *) fun_clos->var_env,
75230  (duk_heaphdr *) fun_clos->lex_env));
75231 
75232  /* Call handling assumes this for all callable closures. */
75233  DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
75234  DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
75235 
75236  /*
75237  * Copy some internal properties directly
75238  *
75239  * The properties will be non-writable and non-enumerable, but
75240  * configurable.
75241  */
75242 
75243  /* [ ... closure template ] */
75244 
75245  DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
75246  (duk_tval *) duk_get_tval(ctx, -2),
75247  (duk_tval *) duk_get_tval(ctx, -1)));
75248 
75249  for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
75250  duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
75251  if (duk_get_prop_stridx_short(ctx, -1, stridx)) {
75252  /* [ ... closure template val ] */
75253  DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
75254  duk_xdef_prop_stridx_short(ctx, -3, stridx, DUK_PROPDESC_FLAGS_C);
75255  } else {
75256  DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
75257  duk_pop(ctx);
75258  }
75259  }
75260 
75261  /*
75262  * "length" maps to number of formals (E5 Section 13.2) for function
75263  * declarations/expressions (non-bound functions). Note that 'nargs'
75264  * is NOT necessarily equal to the number of arguments. Use length
75265  * of _Formals; if missing, assume nargs matches .length.
75266  */
75267 
75268  /* [ ... closure template ] */
75269 
75270  /* XXX: these lookups should be just own property lookups instead of
75271  * looking up the inheritance chain.
75272  */
75273  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_FORMALS)) {
75274  /* [ ... closure template formals ] */
75275  len_value = (duk_uint_t) duk_get_length(ctx, -1); /* could access duk_harray directly, not important */
75276  DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
75277  } else {
75278  len_value = fun_temp->nargs;
75279  DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
75280  }
75281  duk_pop(ctx);
75282 
75283  duk_push_uint(ctx, len_value); /* [ ... closure template len_value ] */
75284  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
75285 
75286  /*
75287  * "prototype" is, by default, a fresh object with the "constructor"
75288  * property.
75289  *
75290  * Note that this creates a circular reference for every function
75291  * instance (closure) which prevents refcount-based collection of
75292  * function instances.
75293  *
75294  * XXX: Try to avoid creating the default prototype object, because
75295  * many functions are not used as constructors and the default
75296  * prototype is unnecessary. Perhaps it could be created on-demand
75297  * when it is first accessed?
75298  */
75299 
75300  /* [ ... closure template ] */
75301 
75302  if (add_auto_proto) {
75303  duk_push_object(ctx); /* -> [ ... closure template newobj ] */
75304  duk_dup_m3(ctx); /* -> [ ... closure template newobj closure ] */
75305  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC); /* -> [ ... closure template newobj ] */
75306  duk_compact(ctx, -1); /* compact the prototype */
75307  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W); /* -> [ ... closure template ] */
75308  }
75309 
75310  /*
75311  * "arguments" and "caller" must be mapped to throwers for strict
75312  * mode and bound functions (E5 Section 15.3.5).
75313  *
75314  * XXX: This is expensive to have for every strict function instance.
75315  * Try to implement as virtual properties or on-demand created properties.
75316  */
75317 
75318  /* [ ... closure template ] */
75319 
75320  if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
75321  duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_CALLER);
75322  duk_xdef_prop_stridx_thrower(ctx, -2, DUK_STRIDX_LC_ARGUMENTS);
75323  } else {
75324 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
75325  DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
75326  duk_push_null(ctx);
75327  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
75328 #else
75329  DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
75330 #endif
75331  }
75332 
75333  /*
75334  * "name" used to be non-standard but is now defined by ES2015.
75335  * In ES2015/ES2016 the .name property is configurable.
75336  */
75337 
75338  /* [ ... closure template ] */
75339 
75340 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
75341  /* XXX: Look for own property only; doesn't matter much because
75342  * templates are bare objects.
75343  */
75344  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_NAME)) {
75345  /* [ ... closure template name ] */
75346  DUK_ASSERT(duk_is_string(ctx, -1));
75347  DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(ctx, -1)));
75348  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C); /* -> [ ... closure template ] */
75349  } else {
75350  /* Anonymous functions don't have a .name in ES2015, so don't set
75351  * it on the instance either. The instance will then inherit
75352  * it from Function.prototype.name.
75353  */
75354  DUK_DD(DUK_DDPRINT("not setting function instance .name"));
75355  duk_pop(ctx);
75356  }
75357 #endif
75358 
75359  /*
75360  * Compact the closure, in most cases no properties will be added later.
75361  * Also, without this the closures end up having unused property slots
75362  * (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
75363  * A better future solution would be to allocate the closure directly
75364  * to correct size (and setup the properties directly without going
75365  * through the API).
75366  */
75367 
75368  duk_compact(ctx, -2);
75369 
75370  /*
75371  * Some assertions (E5 Section 13.2).
75372  */
75373 
75374  DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
75375  DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
75376  DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
75377  DUK_ASSERT(duk_has_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH) != 0);
75378  DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(ctx, -2, DUK_STRIDX_PROTOTYPE) != 0);
75379  /* May be missing .name */
75380  DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
75381  duk_has_prop_stridx(ctx, -2, DUK_STRIDX_CALLER) != 0);
75382  DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
75383  duk_has_prop_stridx(ctx, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
75384 
75385  /*
75386  * Finish
75387  */
75388 
75389  /* [ ... closure template ] */
75390 
75391  DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
75392  (duk_tval *) duk_get_tval(ctx, -1),
75393  (duk_tval *) duk_get_tval(ctx, -2)));
75394 
75395  duk_pop(ctx);
75396 
75397  /* [ ... closure ] */
75398 }
75399 
75400 /*
75401  * Delayed activation environment record initialization (for functions
75402  * with NEWENV).
75403  *
75404  * The non-delayed initialization is handled by duk_handle_call().
75405  */
75406 
75407 /* shared helper */
75408 DUK_INTERNAL
75409 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
75410  duk_hobject *func,
75411  duk_size_t idx_bottom) {
75412  duk_context *ctx = (duk_context *) thr;
75413  duk_hobject *env;
75414  duk_hobject *parent;
75415  duk_hcompfunc *f;
75416 
75417  DUK_ASSERT(thr != NULL);
75418  DUK_ASSERT(func != NULL);
75419 
75420  f = (duk_hcompfunc *) func;
75421  parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
75422  if (!parent) {
75423  parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
75424  }
75425 
75426  (void) duk_push_object_helper(ctx,
75427  DUK_HOBJECT_FLAG_EXTENSIBLE |
75428  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV),
75429  -1); /* no prototype, updated below */
75430  env = duk_known_hobject(ctx, -1);
75431  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, env, parent); /* parent env is the prototype */
75432 
75433  /* open scope information, for compiled functions only */
75434 
75435  if (DUK_HOBJECT_IS_COMPFUNC(func)) {
75436  duk_push_hthread(ctx, thr);
75437  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INT_THREAD);
75438  duk_push_hobject(ctx, func);
75439  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INT_CALLEE);
75440  duk_push_size_t(ctx, idx_bottom);
75441  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INT_REGBASE);
75442  }
75443 
75444  return env;
75445 }
75446 
75447 DUK_INTERNAL
75448 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
75449  duk_activation *act) {
75450  duk_context *ctx = (duk_context *) thr;
75451  duk_hobject *func;
75452  duk_hobject *env;
75453 
75454  func = DUK_ACT_GET_FUNC(act);
75455  DUK_ASSERT(func != NULL);
75456  DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func)); /* bound functions are never in act 'func' */
75457 
75458  /*
75459  * Delayed initialization only occurs for 'NEWENV' functions.
75460  */
75461 
75462  DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
75463  DUK_ASSERT(act->lex_env == NULL);
75464  DUK_ASSERT(act->var_env == NULL);
75465 
75466  env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
75467  DUK_ASSERT(env != NULL);
75468 
75469  DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
75470 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
75471  {
75472  duk_hobject *p = env;
75473  while (p) {
75474  DUK_DDD(DUK_DDDPRINT(" -> %!ipO", (duk_heaphdr *) p));
75475  p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
75476  }
75477  }
75478 #endif
75479 
75480  act->lex_env = env;
75481  act->var_env = env;
75482  DUK_HOBJECT_INCREF(thr, env); /* XXX: incref by count (here 2 times) */
75483  DUK_HOBJECT_INCREF(thr, env);
75484 
75485  duk_pop(ctx);
75486 }
75487 
75488 /*
75489  * Closing environment records.
75490  *
75491  * The environment record MUST be closed with the thread where its activation
75492  * is. In other words (if 'env' is open):
75493  *
75494  * - 'thr' must match _env.thread
75495  * - 'func' must match _env.callee
75496  * - 'regbase' must match _env.regbase
75497  *
75498  * These are not looked up from the env to minimize code size.
75499  *
75500  * XXX: should access the own properties directly instead of using the API
75501  */
75502 
75503 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env, duk_hobject *func, duk_size_t regbase) {
75504  duk_context *ctx = (duk_context *) thr;
75505  duk_uint_fast32_t i;
75506 
75507  DUK_ASSERT(thr != NULL);
75508  DUK_ASSERT(env != NULL);
75509  /* func is NULL for lightfuncs */
75510 
75511  if (!DUK_HOBJECT_IS_DECENV(env) || DUK_HOBJECT_HAS_ENVRECCLOSED(env)) {
75512  DUK_DDD(DUK_DDDPRINT("environment record not a declarative record, "
75513  "or already closed: %!iO",
75514  (duk_heaphdr *) env));
75515  return;
75516  }
75517 
75518  DUK_DDD(DUK_DDDPRINT("closing environment record: %!iO, func: %!iO, regbase: %ld",
75519  (duk_heaphdr *) env, (duk_heaphdr *) func, (long) regbase));
75520 
75521  duk_push_hobject(ctx, env);
75522 
75523  /* assertions: env must be closed in the same thread as where it runs */
75524 #if defined(DUK_USE_ASSERTIONS)
75525  {
75526  /* [... env] */
75527 
75528  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_CALLEE)) {
75529  DUK_ASSERT(duk_is_object(ctx, -1));
75530  DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) func);
75531  }
75532  duk_pop(ctx);
75533 
75534  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_THREAD)) {
75535  DUK_ASSERT(duk_is_object(ctx, -1));
75536  DUK_ASSERT(duk_get_hobject(ctx, -1) == (duk_hobject *) thr);
75537  }
75538  duk_pop(ctx);
75539 
75540  if (duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_REGBASE)) {
75541  DUK_ASSERT(duk_is_number(ctx, -1));
75542  DUK_ASSERT(duk_get_number(ctx, -1) == (double) regbase);
75543  }
75544  duk_pop(ctx);
75545 
75546  /* [... env] */
75547  }
75548 #endif
75549 
75550  if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
75551  duk_hobject *varmap;
75552  duk_hstring *key;
75553  duk_tval *tv;
75554  duk_uint_t regnum;
75555 
75556  /* XXX: additional conditions when to close variables? we don't want to do it
75557  * unless the environment may have "escaped" (referenced in a function closure).
75558  * With delayed environments, the existence is probably good enough of a check.
75559  */
75560 
75561  /* XXX: any way to detect faster whether something needs to be closed?
75562  * We now look up _Callee and then skip the rest.
75563  */
75564 
75565  /* Note: we rely on the _Varmap having a bunch of nice properties, like:
75566  * - being compacted and unmodified during this process
75567  * - not containing an array part
75568  * - having correct value types
75569  */
75570 
75571  /* [... env] */
75572 
75573  if (!duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_CALLEE)) {
75574  DUK_DDD(DUK_DDDPRINT("env has no callee property, nothing to close; re-delete the control properties just in case"));
75575  duk_pop(ctx);
75576  goto skip_varmap;
75577  }
75578 
75579  /* [... env callee] */
75580 
75581  if (!duk_get_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_VARMAP)) {
75582  DUK_DDD(DUK_DDDPRINT("callee has no varmap property, nothing to close; delete the control properties"));
75583  duk_pop_2(ctx);
75584  goto skip_varmap;
75585  }
75586  varmap = duk_require_hobject(ctx, -1);
75587  DUK_ASSERT(varmap != NULL);
75588 
75589  DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
75590 
75591  /* [... env callee varmap] */
75592 
75593  DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
75594 
75595  for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
75596  key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
75597  DUK_ASSERT(key != NULL); /* assume keys are compacted */
75598 
75599  DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i)); /* assume plain values */
75600 
75601  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
75602  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv)); /* assume value is a number */
75603  regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
75604  DUK_ASSERT_DISABLE(regnum >= 0); /* unsigned */
75605  DUK_ASSERT(regnum < ((duk_hcompfunc *) func)->nregs); /* regnum is sane */
75606  DUK_ASSERT(thr->valstack + regbase + regnum >= thr->valstack);
75607  DUK_ASSERT(thr->valstack + regbase + regnum < thr->valstack_top);
75608 
75609  /* XXX: slightly awkward */
75610  duk_push_hstring(ctx, key);
75611  duk_push_tval(ctx, thr->valstack + regbase + regnum);
75612  DUK_DDD(DUK_DDDPRINT("closing identifier '%s' -> reg %ld, value %!T",
75613  (const char *) duk_require_string(ctx, -2),
75614  (long) regnum,
75615  (duk_tval *) duk_get_tval(ctx, -1)));
75616 
75617  /* [... env callee varmap key val] */
75618 
75619  /* if property already exists, overwrites silently */
75620  duk_xdef_prop(ctx, -5, DUK_PROPDESC_FLAGS_WE); /* writable but not deletable */
75621  }
75622 
75623  duk_pop_2(ctx);
75624 
75625  /* [... env] */
75626  }
75627 
75628  skip_varmap:
75629 
75630  /* [... env] */
75631 
75632  duk_del_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_CALLEE);
75633  duk_del_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_THREAD);
75634  duk_del_prop_stridx_short(ctx, -1, DUK_STRIDX_INT_REGBASE);
75635 
75636  duk_pop(ctx);
75637 
75638  DUK_HOBJECT_SET_ENVRECCLOSED(env);
75639 
75640  DUK_DDD(DUK_DDDPRINT("environment record after being closed: %!O",
75641  (duk_heaphdr *) env));
75642 }
75643 
75644 /*
75645  * GETIDREF: a GetIdentifierReference-like helper.
75646  *
75647  * Provides a parent traversing lookup and a single level lookup
75648  * (for HasBinding).
75649  *
75650  * Instead of returning the value, returns a bunch of values allowing
75651  * the caller to read, write, or delete the binding. Value pointers
75652  * are duk_tval pointers which can be mutated directly as long as
75653  * refcounts are properly updated. Note that any operation which may
75654  * reallocate valstacks or compact objects may invalidate the returned
75655  * duk_tval (but not object) pointers, so caller must be very careful.
75656  *
75657  * If starting environment record 'env' is given, 'act' is ignored.
75658  * However, if 'env' is NULL, the caller may identify, in 'act', an
75659  * activation which hasn't had its declarative environment initialized
75660  * yet. The activation registers are then looked up, and its parent
75661  * traversed normally.
75662  *
75663  * The 'out' structure values are only valid if the function returns
75664  * success (non-zero).
75665  */
75666 
75667 /* lookup name from an open declarative record's registers */
75668 DUK_LOCAL
75669 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
75670  duk_hstring *name,
75671  duk_hobject *env,
75672  duk__id_lookup_result *out) {
75673  duk_hthread *env_thr;
75674  duk_hobject *env_func;
75675  duk_size_t env_regbase;
75676  duk_hobject *varmap;
75677  duk_tval *tv;
75678  duk_size_t reg_rel;
75679  duk_size_t idx;
75680 
75681  DUK_ASSERT(thr != NULL);
75682  DUK_ASSERT(name != NULL);
75683  DUK_ASSERT(env != NULL);
75684  DUK_ASSERT(out != NULL);
75685 
75686  DUK_ASSERT(DUK_HOBJECT_IS_DECENV(env));
75687 
75688  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr));
75689  if (!tv) {
75690  /* env is closed, should be missing _Callee, _Thread, _Regbase */
75691  DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_CALLEE(thr)) == NULL);
75692  DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr)) == NULL);
75693  DUK_ASSERT(duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr)) == NULL);
75694  return 0;
75695  }
75696 
75697  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
75698  DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
75699  DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_TVAL_GET_OBJECT(tv)));
75700  env_func = DUK_TVAL_GET_OBJECT(tv);
75701  DUK_ASSERT(env_func != NULL);
75702 
75703  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env_func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
75704  if (!tv) {
75705  return 0;
75706  }
75707  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
75708  varmap = DUK_TVAL_GET_OBJECT(tv);
75709  DUK_ASSERT(varmap != NULL);
75710 
75711  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
75712  if (!tv) {
75713  return 0;
75714  }
75715  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
75716  reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
75717  DUK_ASSERT_DISABLE(reg_rel >= 0); /* unsigned */
75718  DUK_ASSERT(reg_rel < ((duk_hcompfunc *) env_func)->nregs);
75719 
75720  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THREAD(thr));
75721  DUK_ASSERT(tv != NULL);
75722  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
75723  DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
75724  DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
75725  env_thr = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
75726  DUK_ASSERT(env_thr != NULL);
75727 
75728  /* Note: env_thr != thr is quite possible and normal, so careful
75729  * with what thread is used for valstack lookup.
75730  */
75731 
75732  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_REGBASE(thr));
75733  DUK_ASSERT(tv != NULL);
75734  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
75735  env_regbase = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
75736 
75737  idx = env_regbase + reg_rel;
75738  tv = env_thr->valstack + idx;
75739  DUK_ASSERT(tv >= env_thr->valstack && tv < env_thr->valstack_end); /* XXX: more accurate? */
75740 
75741  out->value = tv;
75742  out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
75743  out->this_binding = NULL; /* implicit this value always undefined for
75744  * declarative environment records.
75745  */
75746  out->env = env;
75747  out->holder = NULL;
75748 
75749  return 1;
75750 }
75751 
75752 /* lookup name from current activation record's functions' registers */
75753 DUK_LOCAL
75754 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
75755  duk_hstring *name,
75756  duk_activation *act,
75757  duk__id_lookup_result *out) {
75758  duk_tval *tv;
75759  duk_hobject *func;
75760  duk_hobject *varmap;
75761  duk_size_t reg_rel;
75762  duk_size_t idx;
75763 
75764  DUK_ASSERT(thr != NULL);
75765  DUK_ASSERT(name != NULL);
75766  DUK_ASSERT(act != NULL);
75767  DUK_ASSERT(out != NULL);
75768 
75769  func = DUK_ACT_GET_FUNC(act);
75770  DUK_ASSERT(func != NULL);
75771  DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
75772 
75773  if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
75774  return 0;
75775  }
75776 
75777  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
75778  if (!tv) {
75779  return 0;
75780  }
75781  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
75782  varmap = DUK_TVAL_GET_OBJECT(tv);
75783  DUK_ASSERT(varmap != NULL);
75784 
75785  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
75786  if (!tv) {
75787  return 0;
75788  }
75789  DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
75790  reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
75791  DUK_ASSERT_DISABLE(reg_rel >= 0);
75792  DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
75793 
75794  idx = act->idx_bottom + reg_rel;
75795  DUK_ASSERT(idx >= act->idx_bottom);
75796  tv = thr->valstack + idx;
75797 
75798  out->value = tv;
75799  out->attrs = DUK_PROPDESC_FLAGS_W; /* registers are mutable, non-deletable */
75800  out->this_binding = NULL; /* implicit this value always undefined for
75801  * declarative environment records.
75802  */
75803  out->env = NULL;
75804  out->holder = NULL;
75805 
75806  return 1;
75807 }
75808 
75809 DUK_LOCAL
75810 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
75811  duk_hobject *env,
75812  duk_hstring *name,
75813  duk_activation *act,
75814  duk_bool_t parents,
75815  duk__id_lookup_result *out) {
75816  duk_tval *tv;
75817  duk_tval *tv_target;
75818  duk_tval tv_name;
75819  duk_uint_t sanity;
75820 
75821  DUK_ASSERT(thr != NULL);
75822  DUK_ASSERT(env != NULL || act != NULL);
75823  DUK_ASSERT(name != NULL);
75824  DUK_ASSERT(out != NULL);
75825 
75826  DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
75827  DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
75828 
75829  /*
75830  * Conceptually, we look for the identifier binding by starting from
75831  * 'env' and following to chain of environment records (represented
75832  * by the prototype chain).
75833  *
75834  * If 'env' is NULL, the current activation does not yet have an
75835  * allocated declarative environment record; this should be treated
75836  * exactly as if the environment record existed but had no bindings
75837  * other than register bindings.
75838  *
75839  * Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
75840  * the environment will always be initialized immediately; hence
75841  * a NULL 'env' should only happen with the flag set. This is the
75842  * case for: (1) function calls, and (2) strict, direct eval calls.
75843  */
75844 
75845  if (env == NULL && act != NULL) {
75846  duk_hobject *func;
75847  duk_hcompfunc *f;
75848 
75849  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
75850  "delayed env case, look up activation regs first"));
75851 
75852  /*
75853  * Try registers
75854  */
75855 
75856  if (duk__getid_activation_regs(thr, name, act, out)) {
75857  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
75858  "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
75859  "(found from register bindings when env=NULL)",
75860  (duk_heaphdr *) name, (duk_tval *) out->value,
75861  (long) out->attrs, (duk_tval *) out->this_binding,
75862  (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
75863  return 1;
75864  }
75865 
75866  DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
75867 
75868  /*
75869  * Not found in registers, proceed to the parent record.
75870  * Here we need to determine what the parent would be,
75871  * if 'env' was not NULL (i.e. same logic as when initializing
75872  * the record).
75873  *
75874  * Note that environment initialization is only deferred when
75875  * DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
75876  * - Function code
75877  * - Strict eval code
75878  *
75879  * We only need to check _Lexenv here; _Varenv exists only if it
75880  * differs from _Lexenv (and thus _Lexenv will also be present).
75881  */
75882 
75883  if (!parents) {
75884  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
75885  "(not found from register bindings when env=NULL)"));
75886  goto fail_not_found;
75887  }
75888 
75889  func = DUK_ACT_GET_FUNC(act);
75890  DUK_ASSERT(func != NULL);
75891  DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
75892  f = (duk_hcompfunc *) func;
75893 
75894  env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
75895  if (!env) {
75896  env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
75897  }
75898 
75899  DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
75900  (duk_heaphdr *) env));
75901  }
75902 
75903  /*
75904  * Prototype walking starting from 'env'.
75905  *
75906  * ('act' is not needed anywhere here.)
75907  */
75908 
75909  sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
75910  while (env != NULL) {
75911  duk_small_int_t cl;
75912  duk_int_t attrs;
75913 
75914  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
75915  (duk_heaphdr *) name,
75916  (void *) env,
75917  (duk_heaphdr *) env));
75918 
75919  DUK_ASSERT(env != NULL);
75920  DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
75921  DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
75922 
75923  cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
75924  DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
75925  if (cl == DUK_HOBJECT_CLASS_DECENV) {
75926  /*
75927  * Declarative environment record.
75928  *
75929  * Identifiers can never be stored in ancestors and are
75930  * always plain values, so we can use an internal helper
75931  * and access the value directly with an duk_tval ptr.
75932  *
75933  * A closed environment is only indicated by it missing
75934  * the "book-keeping" properties required for accessing
75935  * register-bound variables.
75936  */
75937 
75938  if (DUK_HOBJECT_HAS_ENVRECCLOSED(env)) {
75939  /* already closed */
75940  goto skip_regs;
75941  }
75942 
75943  if (duk__getid_open_decl_env_regs(thr, name, env, out)) {
75944  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
75945  "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
75946  "(declarative environment record, scope open, found in regs)",
75947  (duk_heaphdr *) name, (duk_tval *) out->value,
75948  (long) out->attrs, (duk_tval *) out->this_binding,
75949  (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
75950  return 1;
75951  }
75952  skip_regs:
75953 
75954  tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
75955  if (tv) {
75956  out->value = tv;
75957  out->attrs = attrs;
75958  out->this_binding = NULL; /* implicit this value always undefined for
75959  * declarative environment records.
75960  */
75961  out->env = env;
75962  out->holder = env;
75963 
75964  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
75965  "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
75966  "(declarative environment record, found in properties)",
75967  (duk_heaphdr *) name, (duk_tval *) out->value,
75968  (long) out->attrs, (duk_tval *) out->this_binding,
75969  (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
75970  return 1;
75971  }
75972  } else {
75973  /*
75974  * Object environment record.
75975  *
75976  * Binding (target) object is an external, uncontrolled object.
75977  * Identifier may be bound in an ancestor property, and may be
75978  * an accessor. Target can also be a Proxy which we must support
75979  * here.
75980  */
75981 
75982  /* XXX: we could save space by using _Target OR _This. If _Target, assume
75983  * this binding is undefined. If _This, assumes this binding is _This, and
75984  * target is also _This. One property would then be enough.
75985  */
75986 
75987  duk_hobject *target;
75988  duk_bool_t found;
75989 
75990  DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
75991 
75992  tv_target = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
75993  DUK_ASSERT(tv_target != NULL);
75994  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_target));
75995  target = DUK_TVAL_GET_OBJECT(tv_target);
75996  DUK_ASSERT(target != NULL);
75997 
75998  /* Target may be a Proxy or property may be an accessor, so we must
75999  * use an actual, Proxy-aware hasprop check here.
76000  *
76001  * out->holder is NOT set to the actual duk_hobject where the
76002  * property is found, but rather the object binding target object.
76003  */
76004 
76005  if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(target)) {
76006  DUK_ASSERT(name != NULL);
76007  DUK_TVAL_SET_STRING(&tv_name, name);
76008 
76009  found = duk_hobject_hasprop(thr, tv_target, &tv_name);
76010  } else {
76011  /* XXX: duk_hobject_hasprop() would be correct for
76012  * non-Proxy objects too, but it is about ~20-25%
76013  * slower at present so separate code paths for
76014  * Proxy and non-Proxy now.
76015  */
76016  found = duk_hobject_hasprop_raw(thr, target, name);
76017  }
76018 
76019  if (found) {
76020  out->value = NULL; /* can't get value, may be accessor */
76021  out->attrs = 0; /* irrelevant when out->value == NULL */
76022  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_THIS(thr));
76023  out->this_binding = tv; /* may be NULL */
76024  out->env = env;
76025  out->holder = target;
76026 
76027  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
76028  "name=%!O -> value=%!T, attrs=%ld, this=%!T, env=%!O, holder=%!O "
76029  "(object environment record)",
76030  (duk_heaphdr *) name, (duk_tval *) out->value,
76031  (long) out->attrs, (duk_tval *) out->this_binding,
76032  (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
76033  return 1;
76034  }
76035  }
76036 
76037  if (!parents) {
76038  DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
76039  "(not found from first traversed env)"));
76040  goto fail_not_found;
76041  }
76042 
76043  if (sanity-- == 0) {
76044  DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
76045  }
76046  env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
76047  };
76048 
76049  /*
76050  * Not found (even in global object)
76051  */
76052 
76053  fail_not_found:
76054  return 0;
76055 }
76056 
76057 /*
76058  * HASVAR: check identifier binding from a given environment record
76059  * without traversing its parents.
76060  *
76061  * This primitive is not exposed to user code as such, but is used
76062  * internally for e.g. declaration binding instantiation.
76063  *
76064  * See E5 Sections:
76065  * 10.2.1.1.1 HasBinding(N)
76066  * 10.2.1.2.1 HasBinding(N)
76067  *
76068  * Note: strictness has no bearing on this check. Hence we don't take
76069  * a 'strict' parameter.
76070  */
76071 
76072 #if 0 /*unused*/
76073 DUK_INTERNAL
76074 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
76075  duk_hobject *env,
76076  duk_hstring *name) {
76078  duk_bool_t parents;
76079 
76080  DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
76081  "(env -> %!dO)",
76082  (void *) thr, (void *) env, (duk_heaphdr *) name,
76083  (duk_heaphdr *) env));
76084 
76085  DUK_ASSERT(thr != NULL);
76086  DUK_ASSERT(env != NULL);
76087  DUK_ASSERT(name != NULL);
76088 
76089  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
76090  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
76091 
76092  DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
76093  DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
76094 
76095  /* lookup results is ignored */
76096  parents = 0;
76097  return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
76098 }
76099 #endif
76100 
76101 /*
76102  * GETVAR
76103  *
76104  * See E5 Sections:
76105  * 11.1.2 Identifier Reference
76106  * 10.3.1 Identifier Resolution
76107  * 11.13.1 Simple Assignment [example of where the Reference is GetValue'd]
76108  * 8.7.1 GetValue (V)
76109  * 8.12.1 [[GetOwnProperty]] (P)
76110  * 8.12.2 [[GetProperty]] (P)
76111  * 8.12.3 [[Get]] (P)
76112  *
76113  * If 'throw' is true, always leaves two values on top of stack: [val this].
76114  *
76115  * If 'throw' is false, returns 0 if identifier cannot be resolved, and the
76116  * stack will be unaffected in this case. If identifier is resolved, returns
76117  * 1 and leaves [val this] on top of stack.
76118  *
76119  * Note: the 'strict' flag of a reference returned by GetIdentifierReference
76120  * is ignored by GetValue. Hence we don't take a 'strict' parameter.
76121  *
76122  * The 'throw' flag is needed for implementing 'typeof' for an unreferenced
76123  * identifier. An unreference identifier in other contexts generates a
76124  * ReferenceError.
76125  */
76126 
76127 DUK_LOCAL
76128 duk_bool_t duk__getvar_helper(duk_hthread *thr,
76129  duk_hobject *env,
76130  duk_activation *act,
76131  duk_hstring *name,
76132  duk_bool_t throw_flag) {
76133  duk_context *ctx = (duk_context *) thr;
76135  duk_tval tv_tmp_obj;
76136  duk_tval tv_tmp_key;
76137  duk_bool_t parents;
76138 
76139  DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
76140  "(env -> %!dO)",
76141  (void *) thr, (void *) env, (void *) act,
76142  (duk_heaphdr *) name, (duk_heaphdr *) env));
76143 
76144  DUK_ASSERT(thr != NULL);
76145  DUK_ASSERT(name != NULL);
76146  /* env and act may be NULL */
76147 
76148  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
76149  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
76150 
76151  parents = 1; /* follow parent chain */
76152  if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
76153  if (ref.value) {
76154  DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
76155  duk_push_tval(ctx, ref.value);
76156  duk_push_undefined(ctx);
76157  } else {
76158  DUK_ASSERT(ref.holder != NULL);
76159 
76160  /* Note: getprop may invoke any getter and invalidate any
76161  * duk_tval pointers, so this must be done first.
76162  */
76163 
76164  if (ref.this_binding) {
76165  duk_push_tval(ctx, ref.this_binding);
76166  } else {
76167  duk_push_undefined(ctx);
76168  }
76169 
76170  DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
76171  DUK_TVAL_SET_STRING(&tv_tmp_key, name);
76172  (void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key); /* [this value] */
76173 
76174  /* ref.value, ref.this.binding invalidated here by getprop call */
76175 
76176  duk_insert(ctx, -2); /* [this value] -> [value this] */
76177  }
76178 
76179  return 1;
76180  } else {
76181  if (throw_flag) {
76182  DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
76183  "identifier '%s' undefined",
76184  (const char *) DUK_HSTRING_GET_DATA(name));
76185  }
76186 
76187  return 0;
76188  }
76189 }
76190 
76191 DUK_INTERNAL
76192 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
76193  duk_hobject *env,
76194  duk_hstring *name,
76195  duk_bool_t throw_flag) {
76196  return duk__getvar_helper(thr, env, NULL, name, throw_flag);
76197 }
76198 
76199 DUK_INTERNAL
76200 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
76201  duk_activation *act,
76202  duk_hstring *name,
76203  duk_bool_t throw_flag) {
76204  DUK_ASSERT(act != NULL);
76205  return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
76206 }
76207 
76208 /*
76209  * PUTVAR
76210  *
76211  * See E5 Sections:
76212  * 11.1.2 Identifier Reference
76213  * 10.3.1 Identifier Resolution
76214  * 11.13.1 Simple Assignment [example of where the Reference is PutValue'd]
76215  * 8.7.2 PutValue (V,W) [see especially step 3.b, undefined -> automatic global in non-strict mode]
76216  * 8.12.4 [[CanPut]] (P)
76217  * 8.12.5 [[Put]] (P)
76218  *
76219  * Note: may invalidate any valstack (or object) duk_tval pointers because
76220  * putting a value may reallocate any object or any valstack. Caller beware.
76221  */
76222 
76223 DUK_LOCAL
76224 void duk__putvar_helper(duk_hthread *thr,
76225  duk_hobject *env,
76226  duk_activation *act,
76227  duk_hstring *name,
76228  duk_tval *val,
76229  duk_bool_t strict) {
76231  duk_tval tv_tmp_obj;
76232  duk_tval tv_tmp_key;
76233  duk_bool_t parents;
76234 
76235  DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
76236  "(env -> %!dO, val -> %!T)",
76237  (void *) thr, (void *) env, (void *) act,
76238  (duk_heaphdr *) name, (void *) val, (long) strict,
76239  (duk_heaphdr *) env, (duk_tval *) val));
76240 
76241  DUK_ASSERT(thr != NULL);
76242  DUK_ASSERT(name != NULL);
76243  DUK_ASSERT(val != NULL);
76244  /* env and act may be NULL */
76245 
76246  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
76247  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
76248  DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
76249 
76250  /*
76251  * In strict mode E5 protects 'eval' and 'arguments' from being
76252  * assigned to (or even declared anywhere). Attempt to do so
76253  * should result in a compile time SyntaxError. See the internal
76254  * design documentation for details.
76255  *
76256  * Thus, we should never come here, run-time, for strict code,
76257  * and name 'eval' or 'arguments'.
76258  */
76259 
76260  DUK_ASSERT(!strict ||
76261  (name != DUK_HTHREAD_STRING_EVAL(thr) &&
76262  name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
76263 
76264  /*
76265  * Lookup variable and update in-place if found.
76266  */
76267 
76268  parents = 1; /* follow parent chain */
76269 
76270  if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
76271  if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
76272  /* Update duk_tval in-place if pointer provided and the
76273  * property is writable. If the property is not writable
76274  * (immutable binding), use duk_hobject_putprop() which
76275  * will respect mutability.
76276  */
76277  duk_tval *tv_val;
76278 
76279  DUK_ASSERT(ref.this_binding == NULL); /* always for register bindings */
76280 
76281  tv_val = ref.value;
76282  DUK_ASSERT(tv_val != NULL);
76283  DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val); /* side effects */
76284 
76285  /* ref.value and ref.this_binding invalidated here */
76286  } else {
76287  DUK_ASSERT(ref.holder != NULL);
76288 
76289  DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
76290  DUK_TVAL_SET_STRING(&tv_tmp_key, name);
76291  (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
76292 
76293  /* ref.value and ref.this_binding invalidated here */
76294  }
76295 
76296  return;
76297  }
76298 
76299  /*
76300  * Not found: write to global object (non-strict) or ReferenceError
76301  * (strict); see E5 Section 8.7.2, step 3.
76302  */
76303 
76304  if (strict) {
76305  DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
76306  DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
76307  "identifier '%s' undefined",
76308  (const char *) DUK_HSTRING_GET_DATA(name));
76309  }
76310 
76311  DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
76312 
76313  DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
76314  DUK_TVAL_SET_STRING(&tv_tmp_key, name);
76315  (void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0); /* 0 = no throw */
76316 
76317  /* NB: 'val' may be invalidated here because put_value may realloc valstack,
76318  * caller beware.
76319  */
76320 }
76321 
76322 DUK_INTERNAL
76323 void duk_js_putvar_envrec(duk_hthread *thr,
76324  duk_hobject *env,
76325  duk_hstring *name,
76326  duk_tval *val,
76327  duk_bool_t strict) {
76328  duk__putvar_helper(thr, env, NULL, name, val, strict);
76329 }
76330 
76331 DUK_INTERNAL
76332 void duk_js_putvar_activation(duk_hthread *thr,
76333  duk_activation *act,
76334  duk_hstring *name,
76335  duk_tval *val,
76336  duk_bool_t strict) {
76337  DUK_ASSERT(act != NULL);
76338  duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
76339 }
76340 
76341 /*
76342  * DELVAR
76343  *
76344  * See E5 Sections:
76345  * 11.4.1 The delete operator
76346  * 10.2.1.1.5 DeleteBinding (N) [declarative environment record]
76347  * 10.2.1.2.5 DeleteBinding (N) [object environment record]
76348  *
76349  * Variable bindings established inside eval() are deletable (configurable),
76350  * other bindings are not, including variables declared in global level.
76351  * Registers are always non-deletable, and the deletion of other bindings
76352  * is controlled by the configurable flag.
76353  *
76354  * For strict mode code, the 'delete' operator should fail with a compile
76355  * time SyntaxError if applied to identifiers. Hence, no strict mode
76356  * run-time deletion of identifiers should ever happen. This function
76357  * should never be called from strict mode code!
76358  */
76359 
76360 DUK_LOCAL
76361 duk_bool_t duk__delvar_helper(duk_hthread *thr,
76362  duk_hobject *env,
76363  duk_activation *act,
76364  duk_hstring *name) {
76366  duk_bool_t parents;
76367 
76368  DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
76369  "(env -> %!dO)",
76370  (void *) thr, (void *) env, (void *) act,
76371  (duk_heaphdr *) name, (duk_heaphdr *) env));
76372 
76373  DUK_ASSERT(thr != NULL);
76374  DUK_ASSERT(name != NULL);
76375  /* env and act may be NULL */
76376 
76377  DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
76378 
76379  parents = 1; /* follow parent chain */
76380 
76381  if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
76382  if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
76383  /* Identifier found in registers (always non-deletable)
76384  * or declarative environment record and non-configurable.
76385  */
76386  return 0;
76387  }
76388  DUK_ASSERT(ref.holder != NULL);
76389 
76390  return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
76391  }
76392 
76393  /*
76394  * Not found (even in global object).
76395  *
76396  * In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
76397  * step 3.b. In strict mode this case is a compile time SyntaxError so
76398  * we should not come here.
76399  */
76400 
76401  DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
76402  "(treated as silent success)",
76403  (duk_heaphdr *) name));
76404  return 1;
76405 }
76406 
76407 #if 0 /*unused*/
76408 DUK_INTERNAL
76409 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
76410  duk_hobject *env,
76411  duk_hstring *name) {
76412  return duk__delvar_helper(thr, env, NULL, name);
76413 }
76414 #endif
76415 
76416 DUK_INTERNAL
76417 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
76418  duk_activation *act,
76419  duk_hstring *name) {
76420  DUK_ASSERT(act != NULL);
76421  return duk__delvar_helper(thr, act->lex_env, act, name);
76422 }
76423 
76424 /*
76425  * DECLVAR
76426  *
76427  * See E5 Sections:
76428  * 10.4.3 Entering Function Code
76429  * 10.5 Declaration Binding Instantion
76430  * 12.2 Variable Statement
76431  * 11.1.2 Identifier Reference
76432  * 10.3.1 Identifier Resolution
76433  *
76434  * Variable declaration behavior is mainly discussed in Section 10.5,
76435  * and is not discussed in the execution semantics (Sections 11-13).
76436  *
76437  * Conceptually declarations happen when code (global, eval, function)
76438  * is entered, before any user code is executed. In practice, register-
76439  * bound identifiers are 'declared' automatically (by virtue of being
76440  * allocated to registers with the initial value 'undefined'). Other
76441  * identifiers are declared in the function prologue with this primitive.
76442  *
76443  * Since non-register bindings eventually back to an internal object's
76444  * properties, the 'prop_flags' argument is used to specify binding
76445  * type:
76446  *
76447  * - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
76448  * - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
76449  * - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
76450  * doesn't really matter for internal objects
76451  *
76452  * All bindings are non-deletable mutable bindings except:
76453  *
76454  * - Declarations in eval code (mutable, deletable)
76455  * - 'arguments' binding in strict function code (immutable)
76456  * - Function name binding of a function expression (immutable)
76457  *
76458  * Declarations may go to declarative environment records (always
76459  * so for functions), but may also go to object environment records
76460  * (e.g. global code). The global object environment has special
76461  * behavior when re-declaring a function (but not a variable); see
76462  * E5.1 specification, Section 10.5, step 5.e.
76463  *
76464  * Declarations always go to the 'top-most' environment record, i.e.
76465  * we never check the record chain. It's not an error even if a
76466  * property (even an immutable or non-deletable one) of the same name
76467  * already exists.
76468  *
76469  * If a declared variable already exists, its value needs to be updated
76470  * (if possible). Returns 1 if a PUTVAR needs to be done by the caller;
76471  * otherwise returns 0.
76472  */
76473 
76474 DUK_LOCAL
76475 duk_bool_t duk__declvar_helper(duk_hthread *thr,
76476  duk_hobject *env,
76477  duk_hstring *name,
76478  duk_tval *val,
76479  duk_small_int_t prop_flags,
76480  duk_bool_t is_func_decl) {
76481  duk_context *ctx = (duk_context *) thr;
76482  duk_hobject *holder;
76483  duk_bool_t parents;
76485  duk_tval *tv;
76486 
76487  DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
76488  "(env -> %!iO)",
76489  (void *) thr, (void *) env, (duk_heaphdr *) name,
76490  (duk_tval *) val, (unsigned long) prop_flags,
76491  (unsigned int) is_func_decl, (duk_heaphdr *) env));
76492 
76493  DUK_ASSERT(thr != NULL);
76494  DUK_ASSERT(env != NULL);
76495  DUK_ASSERT(name != NULL);
76496  DUK_ASSERT(val != NULL);
76497 
76498  /* Note: in strict mode the compiler should reject explicit
76499  * declaration of 'eval' or 'arguments'. However, internal
76500  * bytecode may declare 'arguments' in the function prologue.
76501  * We don't bother checking (or asserting) for these now.
76502  */
76503 
76504  /* Note: val is a stable duk_tval pointer. The caller makes
76505  * a value copy into its stack frame, so 'tv_val' is not subject
76506  * to side effects here.
76507  */
76508 
76509  /*
76510  * Check whether already declared.
76511  *
76512  * We need to check whether the binding exists in the environment
76513  * without walking its parents. However, we still need to check
76514  * register-bound identifiers and the prototype chain of an object
76515  * environment target object.
76516  */
76517 
76518  parents = 0; /* just check 'env' */
76519  if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
76520  duk_int_t e_idx;
76521  duk_int_t h_idx;
76522  duk_small_int_t flags;
76523 
76524  /*
76525  * Variable already declared, ignore re-declaration.
76526  * The only exception is the updated behavior of E5.1 for
76527  * global function declarations, E5.1 Section 10.5, step 5.e.
76528  * This behavior does not apply to global variable declarations.
76529  */
76530 
76531  if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
76532  DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
76533  return 1; /* 1 -> needs a PUTVAR */
76534  }
76535 
76536  /*
76537  * Special behavior in E5.1.
76538  *
76539  * Note that even though parents == 0, the conflicting property
76540  * may be an inherited property (currently our global object's
76541  * prototype is Object.prototype). Step 5.e first operates on
76542  * the existing property (which is potentially in an ancestor)
76543  * and then defines a new property in the global object (and
76544  * never modifies the ancestor).
76545  *
76546  * Also note that this logic would become even more complicated
76547  * if the conflicting property might be a virtual one. Object
76548  * prototype has no virtual properties, though.
76549  *
76550  * XXX: this is now very awkward, rework.
76551  */
76552 
76553  DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
76554  "updated E5.1 processing"));
76555 
76556  DUK_ASSERT(ref.holder != NULL);
76557  holder = ref.holder;
76558 
76559  /* holder will be set to the target object, not the actual object
76560  * where the property was found (see duk__get_identifier_reference()).
76561  */
76562  DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
76563  DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder)); /* global object doesn't have array part */
76564 
76565  /* XXX: use a helper for prototype traversal; no loop check here */
76566  /* must be found: was found earlier, and cannot be inherited */
76567  for (;;) {
76568  DUK_ASSERT(holder != NULL);
76569  duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx);
76570  if (e_idx >= 0) {
76571  break;
76572  }
76573  /* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
76574  * asserted above.
76575  */
76576  holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
76577  }
76578  DUK_ASSERT(holder != NULL);
76579  DUK_ASSERT(e_idx >= 0);
76580  /* SCANBUILD: scan-build produces a NULL pointer dereference warning
76581  * below; it never actually triggers because holder is actually never
76582  * NULL.
76583  */
76584 
76585  /* ref.holder is global object, holder is the object with the
76586  * conflicting property.
76587  */
76588 
76589  flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
76590  if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
76591  if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
76592  DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
76593  "accessor -> reject"));
76594  goto fail_existing_attributes;
76595  }
76596  if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
76597  (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
76598  DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
76599  "plain property which is not writable and "
76600  "enumerable -> reject"));
76601  goto fail_existing_attributes;
76602  }
76603 
76604  DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
76605  "is plain, enumerable, and writable -> "
76606  "allow redeclaration"));
76607  }
76608 
76609  if (holder == ref.holder) {
76610  /* XXX: if duk_hobject_define_property_internal() was updated
76611  * to handle a pre-existing accessor property, this would be
76612  * a simple call (like for the ancestor case).
76613  */
76614  DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
76615 
76616  if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
76617  duk_hobject *tmp;
76618 
76619  tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
76620  DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
76621  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
76622  DUK_UNREF(tmp);
76623  tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
76624  DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
76625  DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
76626  DUK_UNREF(tmp);
76627  } else {
76628  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
76629  DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
76630  }
76631 
76632  /* Here val would be potentially invalid if we didn't make
76633  * a value copy at the caller.
76634  */
76635 
76636  tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
76637  DUK_TVAL_SET_TVAL(tv, val);
76638  DUK_TVAL_INCREF(thr, tv);
76639  DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
76640 
76641  DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
76642  "value -> %!T, prop_flags=0x%08lx",
76643  (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
76644  (unsigned long) prop_flags));
76645  } else {
76646  DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
76647 
76648  DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
76649  duk_push_tval(ctx, val);
76650  duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
76651  }
76652 
76653  return 0;
76654  }
76655 
76656  /*
76657  * Not found (in registers or record objects). Declare
76658  * to current variable environment.
76659  */
76660 
76661  /*
76662  * Get holder object
76663  */
76664 
76665  if (DUK_HOBJECT_IS_DECENV(env)) {
76666  holder = env;
76667  } else {
76668  DUK_ASSERT(DUK_HOBJECT_IS_OBJENV(env));
76669 
76670  tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env, DUK_HTHREAD_STRING_INT_TARGET(thr));
76671  DUK_ASSERT(tv != NULL);
76672  DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
76673  holder = DUK_TVAL_GET_OBJECT(tv);
76674  DUK_ASSERT(holder != NULL);
76675  }
76676 
76677  /*
76678  * Define new property
76679  *
76680  * Note: this may fail if the holder is not extensible.
76681  */
76682 
76683  /* XXX: this is awkward as we use an internal method which doesn't handle
76684  * extensibility etc correctly. Basically we'd want to do a [[DefineOwnProperty]]
76685  * or Object.defineProperty() here.
76686  */
76687 
76688  if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
76689  goto fail_not_extensible;
76690  }
76691 
76692  duk_push_hobject(ctx, holder);
76693  duk_push_hstring(ctx, name);
76694  duk_push_tval(ctx, val);
76695  duk_xdef_prop(ctx, -3, prop_flags); /* [holder name val] -> [holder] */
76696  duk_pop(ctx);
76697 
76698  return 0;
76699 
76700  fail_existing_attributes:
76701  fail_not_extensible:
76702  DUK_ERROR_TYPE(thr, "declaration failed");
76703  return 0;
76704 }
76705 
76706 DUK_INTERNAL
76707 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
76708  duk_activation *act,
76709  duk_hstring *name,
76710  duk_tval *val,
76711  duk_small_int_t prop_flags,
76712  duk_bool_t is_func_decl) {
76713  duk_hobject *env;
76714  duk_tval tv_val_copy;
76715 
76716  /*
76717  * Make a value copy of the input val. This ensures that
76718  * side effects cannot invalidate the pointer.
76719  */
76720 
76721  DUK_TVAL_SET_TVAL(&tv_val_copy, val);
76722  val = &tv_val_copy;
76723 
76724  /*
76725  * Delayed env creation check
76726  */
76727 
76728  if (!act->var_env) {
76729  DUK_ASSERT(act->lex_env == NULL);
76730  duk_js_init_activation_environment_records_delayed(thr, act);
76731  }
76732  DUK_ASSERT(act->lex_env != NULL);
76733  DUK_ASSERT(act->var_env != NULL);
76734 
76735  env = act->var_env;
76736  DUK_ASSERT(env != NULL);
76737  DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
76738 
76739  return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
76740 }
76741 /*
76742  * Lexer for source files, ToNumber() string conversions, RegExp expressions,
76743  * and JSON.
76744  *
76745  * Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer. The
76746  * caller can also rewind the token stream into a certain position which is
76747  * needed by the compiler part for multi-pass scanning. Tokens are
76748  * represented as duk_token structures, and contain line number information.
76749  * Token types are identified with DUK_TOK_* defines.
76750  *
76751  * Characters are decoded into a fixed size lookup window consisting of
76752  * decoded Unicode code points, with window positions past the end of the
76753  * input filled with an invalid codepoint (-1). The tokenizer can thus
76754  * perform multiple character lookups efficiently and with few sanity
76755  * checks (such as access outside the end of the input), which keeps the
76756  * tokenization code small at the cost of performance.
76757  *
76758  * Character data in tokens, such as identifier names and string literals,
76759  * is encoded into CESU-8 format on-the-fly while parsing the token in
76760  * question. The string data is made reachable to garbage collection by
76761  * placing the token-related values in value stack entries allocated for
76762  * this purpose by the caller. The characters exist in Unicode code point
76763  * form only in the fixed size lookup window, which keeps character data
76764  * expansion (of especially ASCII data) low.
76765  *
76766  * Token parsing supports the full range of Unicode characters as described
76767  * in the E5 specification. Parsing has been optimized for ASCII characters
76768  * because ordinary Ecmascript code consists almost entirely of ASCII
76769  * characters. Matching of complex Unicode codepoint sets (such as in the
76770  * IdentifierStart and IdentifierPart productions) is optimized for size,
76771  * and is done using a linear scan of a bit-packed list of ranges. This is
76772  * very slow, but should never be entered unless the source code actually
76773  * contains Unicode characters.
76774  *
76775  * Ecmascript tokenization is partially context sensitive. First,
76776  * additional future reserved words are recognized in strict mode (see E5
76777  * Section 7.6.1.2). Second, a forward slash character ('/') can be
76778  * recognized either as starting a RegExp literal or as a division operator,
76779  * depending on context. The caller must provide necessary context flags
76780  * when requesting a new token.
76781  *
76782  * Future work:
76783  *
76784  * * Make line number tracking optional, as it consumes space.
76785  *
76786  * * Add a feature flag for disabling UTF-8 decoding of input, as most
76787  * source code is ASCII. Because of Unicode escapes written in ASCII,
76788  * this does not allow Unicode support to be removed from e.g.
76789  * duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
76790  * encoding of e.g. string literals.
76791  *
76792  * * Add a feature flag for disabling Unicode compliance of e.g. identifier
76793  * names. This allows for a build more than a kilobyte smaller, because
76794  * Unicode ranges needed by duk_unicode_is_identifier_start() and
76795  * duk_unicode_is_identifier_part() can be dropped. String literals
76796  * should still be allowed to contain escaped Unicode, so this still does
76797  * not allow removal of CESU-8 encoding of e.g. string literals.
76798  *
76799  * * Character lookup tables for codepoints above BMP could be stripped.
76800  *
76801  * * Strictly speaking, E5 specification requires that source code consists
76802  * of 16-bit code units, and if not, must be conceptually converted to
76803  * that format first. The current lexer processes Unicode code points
76804  * and allows characters outside the BMP. These should be converted to
76805  * surrogate pairs while reading the source characters into the window,
76806  * not after tokens have been formed (as is done now). However, the fix
76807  * is not trivial because two characters are decoded from one codepoint.
76808  *
76809  * * Optimize for speed as well as size. Large if-else ladders are (at
76810  * least potentially) slow.
76811  */
76812 
76813 /* #include duk_internal.h -> already included */
76814 
76815 /*
76816  * Various defines and file specific helper macros
76817  */
76818 
76819 #define DUK__MAX_RE_DECESC_DIGITS 9
76820 #define DUK__MAX_RE_QUANT_DIGITS 9 /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
76821 
76822 /* whether to use macros or helper function depends on call count */
76823 #define DUK__ISDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
76824 #define DUK__ISHEXDIGIT(x) duk__is_hex_digit((x))
76825 #define DUK__ISOCTDIGIT(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
76826 #define DUK__ISDIGIT03(x) ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
76827 #define DUK__ISDIGIT47(x) ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
76828 
76829 /* lexer character window helpers */
76830 #define DUK__LOOKUP(lex_ctx,idx) ((lex_ctx)->window[(idx)].codepoint)
76831 #define DUK__ADVANCECHARS(lex_ctx,count) duk__advance_chars((lex_ctx), (count))
76832 #define DUK__ADVANCEBYTES(lex_ctx,count) duk__advance_bytes((lex_ctx), (count))
76833 #define DUK__INITBUFFER(lex_ctx) duk__initbuffer((lex_ctx))
76834 #define DUK__APPENDBUFFER(lex_ctx,x) duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
76835 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x) duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
76836 
76837 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
76838 #define DUK__L0() DUK__LOOKUP(lex_ctx, 0)
76839 #define DUK__L1() DUK__LOOKUP(lex_ctx, 1)
76840 #define DUK__L2() DUK__LOOKUP(lex_ctx, 2)
76841 #define DUK__L3() DUK__LOOKUP(lex_ctx, 3)
76842 #define DUK__L4() DUK__LOOKUP(lex_ctx, 4)
76843 #define DUK__L5() DUK__LOOKUP(lex_ctx, 5)
76844 
76845 /* packed advance/token number macro used by multiple functions */
76846 #define DUK__ADVTOK(advbytes,tok) ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
76847 
76848 /*
76849  * Advance lookup window by N characters, filling in new characters as
76850  * necessary. After returning caller is guaranteed a character window of
76851  * at least DUK_LEXER_WINDOW_SIZE characters.
76852  *
76853  * The main function duk__advance_bytes() is called at least once per every
76854  * token so it has a major lexer/compiler performance impact. There are two
76855  * variants for the main duk__advance_bytes() algorithm: a sliding window
76856  * approach which is slightly faster at the cost of larger code footprint,
76857  * and a simple copying one.
76858  *
76859  * Decoding directly from the source string would be another lexing option.
76860  * But the lookup window based approach has the advantage of hiding the
76861  * source string and its encoding effectively which gives more flexibility
76862  * going forward to e.g. support chunked streaming of source from flash.
76863  *
76864  * Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
76865  * U+10FFFF, causing an error if the input is unparseable. Leniency means:
76866  *
76867  * * Unicode code point validation is intentionally not performed,
76868  * except to check that the codepoint does not exceed 0x10ffff.
76869  *
76870  * * In particular, surrogate pairs are allowed and not combined, which
76871  * allows source files to represent all SourceCharacters with CESU-8.
76872  * Broken surrogate pairs are allowed, as Ecmascript does not mandate
76873  * their validation.
76874  *
76875  * * Allow non-shortest UTF-8 encodings.
76876  *
76877  * Leniency here causes few security concerns because all character data is
76878  * decoded into Unicode codepoints before lexer processing, and is then
76879  * re-encoded into CESU-8. The source can be parsed as strict UTF-8 with
76880  * a compiler option. However, Ecmascript source characters include -all-
76881  * 16-bit unsigned integer codepoints, so leniency seems to be appropriate.
76882  *
76883  * Note that codepoints above the BMP are not strictly SourceCharacters,
76884  * but the lexer still accepts them as such. Before ending up in a string
76885  * or an identifier name, codepoints above BMP are converted into surrogate
76886  * pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
76887  * expected by Ecmascript.
76888  *
76889  * An alternative approach to dealing with invalid or partial sequences
76890  * would be to skip them and replace them with e.g. the Unicode replacement
76891  * character U+FFFD. This has limited utility because a replacement character
76892  * will most likely cause a parse error, unless it occurs inside a string.
76893  * Further, Ecmascript source is typically pure ASCII.
76894  *
76895  * See:
76896  *
76897  * http://en.wikipedia.org/wiki/UTF-8
76898  * http://en.wikipedia.org/wiki/CESU-8
76899  * http://tools.ietf.org/html/rfc3629
76900  * http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
76901  *
76902  * Future work:
76903  *
76904  * * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
76905  * in strict UTF-8 mode.
76906  *
76907  * * Size optimize. An attempt to use a 16-byte lookup table for the first
76908  * byte resulted in a code increase though.
76909  *
76910  * * Is checking against maximum 0x10ffff really useful? 4-byte encoding
76911  * imposes a certain limit anyway.
76912  *
76913  * * Support chunked streaming of source code. Can be implemented either
76914  * by streaming chunks of bytes or chunks of codepoints.
76915  */
76916 
76917 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
76918 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
76919  duk_lexer_codepoint *cp, *cp_end;
76920  duk_ucodepoint_t x;
76921  duk_small_uint_t contlen;
76922  const duk_uint8_t *p, *p_end;
76923 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
76924  duk_ucodepoint_t mincp;
76925 #endif
76926  duk_int_t input_line;
76927 
76928  /* Use temporaries and update lex_ctx only when finished. */
76929  input_line = lex_ctx->input_line;
76930  p = lex_ctx->input + lex_ctx->input_offset;
76931  p_end = lex_ctx->input + lex_ctx->input_length;
76932 
76933  cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
76934  cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
76935 
76936  for (; cp != cp_end; cp++) {
76937  cp->offset = (duk_size_t) (p - lex_ctx->input);
76938  cp->line = input_line;
76939 
76940  /* XXX: potential issue with signed pointers, p_end < p. */
76941  if (DUK_UNLIKELY(p >= p_end)) {
76942  /* If input_offset were assigned a negative value, it would
76943  * result in a large positive value. Most likely it would be
76944  * larger than input_length and be caught here. In any case
76945  * no memory unsafe behavior would happen.
76946  */
76947  cp->codepoint = -1;
76948  continue;
76949  }
76950 
76951  x = (duk_ucodepoint_t) (*p++);
76952 
76953  /* Fast path. */
76954 
76955  if (DUK_LIKELY(x < 0x80UL)) {
76956  DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
76957  if (DUK_UNLIKELY(x <= 0x000dUL)) {
76958  if ((x == 0x000aUL) ||
76959  ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
76960  /* lookup for 0x000a above assumes shortest encoding now */
76961 
76962  /* E5 Section 7.3, treat the following as newlines:
76963  * LF
76964  * CR [not followed by LF]
76965  * LS
76966  * PS
76967  *
76968  * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
76969  * the line number.
76970  */
76971  input_line++;
76972  }
76973  }
76974 
76975  cp->codepoint = (duk_codepoint_t) x;
76976  continue;
76977  }
76978 
76979  /* Slow path. */
76980 
76981  if (x < 0xc0UL) {
76982  /* 10xx xxxx -> invalid */
76983  goto error_encoding;
76984  } else if (x < 0xe0UL) {
76985  /* 110x xxxx 10xx xxxx */
76986  contlen = 1;
76987 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
76988  mincp = 0x80UL;
76989 #endif
76990  x = x & 0x1fUL;
76991  } else if (x < 0xf0UL) {
76992  /* 1110 xxxx 10xx xxxx 10xx xxxx */
76993  contlen = 2;
76994 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
76995  mincp = 0x800UL;
76996 #endif
76997  x = x & 0x0fUL;
76998  } else if (x < 0xf8UL) {
76999  /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
77000  contlen = 3;
77001 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77002  mincp = 0x10000UL;
77003 #endif
77004  x = x & 0x07UL;
77005  } else {
77006  /* no point in supporting encodings of 5 or more bytes */
77007  goto error_encoding;
77008  }
77009 
77010  DUK_ASSERT(p_end >= p);
77011  if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
77012  goto error_clipped;
77013  }
77014 
77015  while (contlen > 0) {
77016  duk_small_uint_t y;
77017  y = *p++;
77018  if ((y & 0xc0U) != 0x80U) {
77019  /* check that byte has the form 10xx xxxx */
77020  goto error_encoding;
77021  }
77022  x = x << 6;
77023  x += y & 0x3fUL;
77024  contlen--;
77025  }
77026 
77027  /* check final character validity */
77028 
77029  if (x > 0x10ffffUL) {
77030  goto error_encoding;
77031  }
77032 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77033  if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
77034  goto error_encoding;
77035  }
77036 #endif
77037 
77038  DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
77039  if ((x == 0x2028UL) || (x == 0x2029UL)) {
77040  input_line++;
77041  }
77042 
77043  cp->codepoint = (duk_codepoint_t) x;
77044  }
77045 
77046  lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
77047  lex_ctx->input_line = input_line;
77048  return;
77049 
77050  error_clipped: /* clipped codepoint */
77051  error_encoding: /* invalid codepoint encoding or codepoint */
77052  lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
77053  lex_ctx->input_line = input_line;
77054 
77055  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_DECODE_FAILED);
77056 }
77057 
77058 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
77059  duk_small_uint_t used_bytes, avail_bytes;
77060 
77061  DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
77062  DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
77063  DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
77064  DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
77065  DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
77066 
77067  /* Zero 'count' is also allowed to make call sites easier.
77068  * Arithmetic in bytes generates better code in GCC.
77069  */
77070 
77071  lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes); /* avoid multiply */
77072  used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
77073  avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
77074  if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
77075  /* Not enough data to provide a full window, so "scroll" window to
77076  * start of buffer and fill up the rest.
77077  */
77078  DUK_MEMMOVE((void *) lex_ctx->buffer,
77079  (const void *) lex_ctx->window,
77080  (size_t) avail_bytes);
77081  lex_ctx->window = lex_ctx->buffer;
77082  duk__fill_lexer_buffer(lex_ctx, avail_bytes);
77083  }
77084 }
77085 
77086 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
77087  lex_ctx->window = lex_ctx->buffer;
77088  duk__fill_lexer_buffer(lex_ctx, 0);
77089 }
77090 #else /* DUK_USE_LEXER_SLIDING_WINDOW */
77091 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
77092  duk_ucodepoint_t x;
77093  duk_small_uint_t len;
77094  duk_small_uint_t i;
77095  const duk_uint8_t *p;
77096 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77097  duk_ucodepoint_t mincp;
77098 #endif
77099  duk_size_t input_offset;
77100 
77101  input_offset = lex_ctx->input_offset;
77102  if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
77103  /* If input_offset were assigned a negative value, it would
77104  * result in a large positive value. Most likely it would be
77105  * larger than input_length and be caught here. In any case
77106  * no memory unsafe behavior would happen.
77107  */
77108  return -1;
77109  }
77110 
77111  p = lex_ctx->input + input_offset;
77112  x = (duk_ucodepoint_t) (*p);
77113 
77114  if (DUK_LIKELY(x < 0x80UL)) {
77115  /* 0xxx xxxx -> fast path */
77116 
77117  /* input offset tracking */
77118  lex_ctx->input_offset++;
77119 
77120  DUK_ASSERT(x != 0x2028UL && x != 0x2029UL); /* not LS/PS */
77121  if (DUK_UNLIKELY(x <= 0x000dUL)) {
77122  if ((x == 0x000aUL) ||
77123  ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
77124  lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
77125  /* lookup for 0x000a above assumes shortest encoding now */
77126 
77127  /* E5 Section 7.3, treat the following as newlines:
77128  * LF
77129  * CR [not followed by LF]
77130  * LS
77131  * PS
77132  *
77133  * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
77134  * the line number.
77135  */
77136  lex_ctx->input_line++;
77137  }
77138  }
77139 
77140  return (duk_codepoint_t) x;
77141  }
77142 
77143  /* Slow path. */
77144 
77145  if (x < 0xc0UL) {
77146  /* 10xx xxxx -> invalid */
77147  goto error_encoding;
77148  } else if (x < 0xe0UL) {
77149  /* 110x xxxx 10xx xxxx */
77150  len = 2;
77151 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77152  mincp = 0x80UL;
77153 #endif
77154  x = x & 0x1fUL;
77155  } else if (x < 0xf0UL) {
77156  /* 1110 xxxx 10xx xxxx 10xx xxxx */
77157  len = 3;
77158 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77159  mincp = 0x800UL;
77160 #endif
77161  x = x & 0x0fUL;
77162  } else if (x < 0xf8UL) {
77163  /* 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx */
77164  len = 4;
77165 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77166  mincp = 0x10000UL;
77167 #endif
77168  x = x & 0x07UL;
77169  } else {
77170  /* no point in supporting encodings of 5 or more bytes */
77171  goto error_encoding;
77172  }
77173 
77174  DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
77175  if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
77176  goto error_clipped;
77177  }
77178 
77179  p++;
77180  for (i = 1; i < len; i++) {
77181  duk_small_uint_t y;
77182  y = *p++;
77183  if ((y & 0xc0U) != 0x80U) {
77184  /* check that byte has the form 10xx xxxx */
77185  goto error_encoding;
77186  }
77187  x = x << 6;
77188  x += y & 0x3fUL;
77189  }
77190 
77191  /* check final character validity */
77192 
77193  if (x > 0x10ffffUL) {
77194  goto error_encoding;
77195  }
77196 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
77197  if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
77198  goto error_encoding;
77199  }
77200 #endif
77201 
77202  /* input offset tracking */
77203  lex_ctx->input_offset += len;
77204 
77205  /* line tracking */
77206  DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
77207  if ((x == 0x2028UL) || (x == 0x2029UL)) {
77208  lex_ctx->input_line++;
77209  }
77210 
77211  return (duk_codepoint_t) x;
77212 
77213  error_clipped: /* clipped codepoint */
77214  error_encoding: /* invalid codepoint encoding or codepoint */
77215  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_DECODE_FAILED);
77216  return 0;
77217 }
77218 
77219 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
77220  duk_small_uint_t keep_bytes;
77221  duk_lexer_codepoint *cp, *cp_end;
77222 
77223  DUK_ASSERT_DISABLE(count_bytes >= 0); /* unsigned */
77224  DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
77225 
77226  /* Zero 'count' is also allowed to make call sites easier. */
77227 
77228  keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
77229  DUK_MEMMOVE((void *) lex_ctx->window,
77230  (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
77231  (size_t) keep_bytes);
77232 
77233  cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
77234  cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
77235  for (; cp != cp_end; cp++) {
77236  cp->offset = lex_ctx->input_offset;
77237  cp->line = lex_ctx->input_line;
77238  cp->codepoint = duk__read_char(lex_ctx);
77239  }
77240 }
77241 
77242 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
77243  /* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
77244  duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)); /* fill window */
77245 }
77246 #endif /* DUK_USE_LEXER_SLIDING_WINDOW */
77247 
77248 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
77249  duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
77250 }
77251 
77252 /*
77253  * (Re)initialize the temporary byte buffer. May be called extra times
77254  * with little impact.
77255  */
77256 
77257 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
77258  /* Reuse buffer as is unless buffer has grown large. */
77259  if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
77260  /* Keep current size */
77261  } else {
77262  duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
77263  }
77264 
77265  DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
77266 }
77267 
77268 /*
77269  * Append a Unicode codepoint to the temporary byte buffer. Performs
77270  * CESU-8 surrogate pair encoding for codepoints above the BMP.
77271  * Existing surrogate pairs are allowed and also encoded into CESU-8.
77272  */
77273 
77274 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
77275  /*
77276  * Since character data is only generated by decoding the source or by
77277  * the compiler itself, we rely on the input codepoints being correct
77278  * and avoid a check here.
77279  *
77280  * Character data can also come here through decoding of Unicode
77281  * escapes ("\udead\ubeef") so all 16-but unsigned values can be
77282  * present, even when the source file itself is strict UTF-8.
77283  */
77284  DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
77285 
77286  DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
77287 }
77288 
77289 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
77290  /* ASCII characters can be emitted as a single byte without encoding
77291  * which matters for some fast paths.
77292  */
77293  DUK_ASSERT(x >= 0 && x <= 0x7f);
77294 
77295  DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
77296 }
77297 
77298 /*
77299  * Intern the temporary byte buffer into a valstack slot
77300  * (in practice, slot1 or slot2).
77301  */
77302 
77303 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
77304  duk_context *ctx = (duk_context *) lex_ctx->thr;
77305 
77306  DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
77307 
77308  DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
77309  duk_replace(ctx, valstack_idx);
77310  return duk_known_hstring(ctx, valstack_idx);
77311 }
77312 
77313 /*
77314  * Init lexer context
77315  */
77316 
77317 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
77318  DUK_ASSERT(lex_ctx != NULL);
77319 
77320  DUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));
77321 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
77322 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
77323  lex_ctx->window = NULL;
77324 #endif
77325  lex_ctx->thr = NULL;
77326  lex_ctx->input = NULL;
77327  lex_ctx->buf = NULL;
77328 #endif
77329 }
77330 
77331 /*
77332  * Set lexer input position and reinitialize lookup window.
77333  */
77334 
77335 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
77336  pt->offset = lex_ctx->window[0].offset;
77337  pt->line = lex_ctx->window[0].line;
77338 }
77339 
77340 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
77341  DUK_ASSERT_DISABLE(pt->offset >= 0); /* unsigned */
77342  DUK_ASSERT(pt->line >= 1);
77343  lex_ctx->input_offset = pt->offset;
77344  lex_ctx->input_line = pt->line;
77345  duk__init_lexer_window(lex_ctx);
77346 }
77347 
77348 /*
77349  * Lexing helpers
77350  */
77351 
77352 /* Numeric value of a hex digit (also covers octal and decimal digits) or
77353  * -1 if not a valid hex digit.
77354  */
77355 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
77356  duk_small_int_t t;
77357 
77358  /* Here 'x' is a Unicode codepoint */
77359  if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
77360  t = duk_hex_dectab[x];
77361  if (DUK_LIKELY(t >= 0)) {
77362  return t;
77363  }
77364  }
77365 
77366  return -1;
77367 }
77368 
77369 /* Just a wrapper for call sites where 'x' is known to be valid so
77370  * we assert for it before decoding.
77371  */
77372 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
77373  duk_codepoint_t ret;
77374 
77375  DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
77376  (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
77377  (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
77378  ret = duk__hexval_validate(x);
77379  DUK_ASSERT(ret >= 0 && ret <= 15);
77380  return ret;
77381 }
77382 
77383 /* having this as a separate function provided a size benefit */
77384 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
77385  if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
77386  return (duk_hex_dectab[x] >= 0);
77387  }
77388  return 0;
77389 }
77390 
77391 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}. Shared by
77392  * source and RegExp parsing.
77393  */
77394 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
77395  duk_small_int_t digits; /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
77396  duk_codepoint_t escval;
77397  duk_codepoint_t x;
77398  duk_small_int_t adv;
77399 
77400  DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH); /* caller responsibilities */
77401  DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
77402  DUK_UNREF(allow_es6);
77403 
77404  adv = 2;
77405  digits = 2;
77406  if (DUK__L1() == DUK_ASC_LC_U) {
77407  digits = 4;
77408 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
77409  if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
77410  digits = 0;
77411  adv = 3;
77412  }
77413 #endif
77414  }
77415  DUK__ADVANCECHARS(lex_ctx, adv);
77416 
77417  escval = 0;
77418  for (;;) {
77419  /* One of the escape forms: \xHH, \uHHHH, \u{H+}.
77420  * The 'digits' variable tracks parsing state and is
77421  * initialized to:
77422  *
77423  * \xHH 2
77424  * \uHH 4
77425  * \u{H+} 0 first time, updated to -1 to indicate
77426  * at least one digit has been parsed
77427  *
77428  * Octal parsing is handled separately because it can be
77429  * done with fixed lookahead and also has validation
77430  * rules which depend on the escape length (which is
77431  * variable).
77432  *
77433  * We don't need a specific check for x < 0 (end of
77434  * input) or duk_unicode_is_line_terminator(x)
77435  * because the 'dig' decode will fail and lead to a
77436  * SyntaxError.
77437  */
77438  duk_codepoint_t dig;
77439 
77440  x = DUK__L0();
77441  DUK__ADVANCECHARS(lex_ctx, 1);
77442 
77443  dig = duk__hexval_validate(x);
77444  if (digits > 0) {
77445  digits--;
77446  if (dig < 0) {
77447  goto fail_escape;
77448  }
77449  DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
77450  escval = (escval << 4) + dig;
77451  if (digits == 0) {
77452  DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
77453  break;
77454  }
77455  } else {
77456 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
77457  DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
77458  if (dig >= 0) {
77459  DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
77460  escval = (escval << 4) + dig;
77461  if (escval > 0x10ffffL) {
77462  goto fail_escape;
77463  }
77464  } else if (x == DUK_ASC_RCURLY) {
77465  if (digits == 0) {
77466  /* Empty escape, \u{}. */
77467  goto fail_escape;
77468  }
77469  DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
77470  break;
77471  } else {
77472  goto fail_escape;
77473  }
77474  digits = -1; /* Indicate we have at least one digit. */
77475 #else /* DUK_USE_ES6_UNICODE_ESCAPE */
77476  DUK_ASSERT(0); /* Never happens if \u{H+} support disabled. */
77477 #endif /* DUK_USE_ES6_UNICODE_ESCAPE */
77478  }
77479  }
77480 
77481  return escval;
77482 
77483  fail_escape:
77484  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
77485 }
77486 
77487 /* XXX: move strict mode to lex_ctx? */
77488 DUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode) {
77489  duk_small_int_t adv;
77490 
77491  for (adv = 1 /* initial quote */ ;;) {
77492  duk_codepoint_t x;
77493 
77494  DUK__ADVANCECHARS(lex_ctx, adv); /* eat opening quote on first loop */
77495  x = DUK__L0();
77496 
77497  adv = 1;
77498  if (x == quote) {
77499  DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing quote */
77500  break;
77501  } else if (x == '\\') {
77502  /* DUK__L0 -> '\' char
77503  * DUK__L1 ... DUK__L5 -> more lookup
77504  */
77505  duk_small_int_t emitcp = -1;
77506 
77507  x = DUK__L1();
77508 
77509  /* How much to advance before next loop. */
77510  adv = 2; /* note: long live range */
77511 
77512  switch (x) {
77513  case '\'':
77514  emitcp = 0x0027;
77515  break;
77516  case '"':
77517  emitcp = 0x0022;
77518  break;
77519  case '\\':
77520  emitcp = 0x005c;
77521  break;
77522  case 'b':
77523  emitcp = 0x0008;
77524  break;
77525  case 'f':
77526  emitcp = 0x000c;
77527  break;
77528  case 'n':
77529  emitcp = 0x000a;
77530  break;
77531  case 'r':
77532  emitcp = 0x000d;
77533  break;
77534  case 't':
77535  emitcp = 0x0009;
77536  break;
77537  case 'v':
77538  emitcp = 0x000b;
77539  break;
77540  case 'x':
77541  case 'u': {
77542  duk_codepoint_t esc_cp;
77543  esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
77544  DUK__APPENDBUFFER(lex_ctx, esc_cp);
77545  adv = 0;
77546  break;
77547  }
77548  default: {
77549  if (duk_unicode_is_line_terminator(x)) {
77550  /* line continuation */
77551  if (x == 0x000d && DUK__L2() == 0x000a) {
77552  /* CR LF again a special case */
77553  adv = 3; /* line terminator, CR, LF */
77554  }
77555  } else if (DUK__ISDIGIT(x)) {
77556  /*
77557  * Octal escape or zero escape:
77558  * \0 (lookahead not OctalDigit)
77559  * \1 ... \7 (lookahead not OctalDigit)
77560  * \ZeroToThree OctalDigit (lookahead not OctalDigit)
77561  * \FourToSeven OctalDigit (no lookahead restrictions)
77562  * \ZeroToThree OctalDigit OctalDigit (no lookahead restrictions)
77563  *
77564  * Zero escape is part of the standard syntax. Octal escapes are
77565  * defined in E5 Section B.1.2, and are only allowed in non-strict mode.
77566  * Any other productions starting with a decimal digit are invalid
77567  * but are in practice treated like identity escapes.
77568  *
77569  * Parse octal (up to 3 digits) from the lookup window.
77570  */
77571 
77572  duk_codepoint_t tmp;
77573  duk_small_uint_t lookup_idx;
77574 
77575  emitcp = 0;
77576  for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
77577  DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, emitcp=%ld", (long) lookup_idx, (long) emitcp));
77578  tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
77579  if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
77580  /* No more valid digits. */
77581  break;
77582  }
77583  tmp = (emitcp << 3) + (tmp - DUK_ASC_0);
77584  if (tmp > 0xff) {
77585  /* Three digit octal escapes above \377 (= 0xff)
77586  * are not allowed.
77587  */
77588  break;
77589  }
77590  emitcp = tmp;
77591  }
77592  DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, emitcp=%ld", (long) lookup_idx, (long) emitcp));
77593 
77594  adv = lookup_idx;
77595  if (lookup_idx == 1) {
77596  /* \8 or \9 -> treat as literal, accept also
77597  * in strict mode.
77598  */
77599  DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
77600  emitcp = x;
77601  adv++; /* correction to above, eat offending character */
77602  } else if (lookup_idx == 2 && emitcp == 0) {
77603  /* Zero escape, also allowed in non-strict mode. */
77604  DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
77605  } else {
77606  /* Valid octal, only accept in non-strict mode. */
77607  DUK_DDD(DUK_DDDPRINT("octal literal %ld -> accept only in non-strict-mode", (long) emitcp));
77608  DUK_ASSERT(emitcp >= 0 && emitcp <= 0xff);
77609  if (strict_mode) {
77610  goto fail_escape;
77611  }
77612  }
77613  } else if (x < 0) {
77614  goto fail_unterminated;
77615  } else {
77616  /* escaped NonEscapeCharacter */
77617  DUK__APPENDBUFFER(lex_ctx, x);
77618  }
77619  } /* end default clause */
77620  } /* end switch */
77621 
77622  /* Shared handling for single codepoint escapes. */
77623  if (emitcp >= 0) {
77624  DUK__APPENDBUFFER(lex_ctx, emitcp);
77625  }
77626 
77627  /* Track number of escapes; count not really needed but directive
77628  * prologues need to detect whether there were any escapes or line
77629  * continuations or not.
77630  */
77631  out_token->num_escapes++;
77632  } else if (x >= 0x20 && x <= 0x7f) {
77633  /* Fast path for ASCII case, avoids line terminator
77634  * check and CESU-8 encoding.
77635  */
77636  DUK_ASSERT(x >= 0);
77637  DUK_ASSERT(!duk_unicode_is_line_terminator(x));
77638  DUK_ASSERT(x != quote);
77639  DUK_ASSERT(x != DUK_ASC_BACKSLASH);
77640  DUK__APPENDBUFFER_ASCII(lex_ctx, x);
77641  } else if (x < 0 || duk_unicode_is_line_terminator(x)) {
77642  goto fail_unterminated;
77643  } else {
77644  /* Character which is part of the string but wasn't handled
77645  * by the fast path.
77646  */
77647  DUK__APPENDBUFFER(lex_ctx, x);
77648  }
77649  } /* string parse loop */
77650 
77651  return;
77652 
77653  fail_escape:
77654  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
77655  return;
77656 
77657  fail_unterminated:
77658  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
77659  return;
77660 }
77661 
77662 /*
77663  * Parse Ecmascript source InputElementDiv or InputElementRegExp
77664  * (E5 Section 7), skipping whitespace, comments, and line terminators.
77665  *
77666  * Possible results are:
77667  * (1) a token
77668  * (2) a line terminator (skipped)
77669  * (3) a comment (skipped)
77670  * (4) EOF
77671  *
77672  * White space is automatically skipped from the current position (but
77673  * not after the input element). If input has already ended, returns
77674  * DUK_TOK_EOF indefinitely. If a parse error occurs, uses an DUK_ERROR()
77675  * macro call (and hence a longjmp through current heap longjmp context).
77676  * Comments and line terminator tokens are automatically skipped.
77677  *
77678  * The input element being matched is determined by regexp_mode; if set,
77679  * parses a InputElementRegExp, otherwise a InputElementDiv. The
77680  * difference between these are handling of productions starting with a
77681  * forward slash.
77682  *
77683  * If strict_mode is set, recognizes additional future reserved words
77684  * specific to strict mode, and refuses to parse octal literals.
77685  *
77686  * The matching strategy below is to (currently) use a six character
77687  * lookup window to quickly determine which production is the -longest-
77688  * matching one, and then parse that. The top-level if-else clauses
77689  * match the first character, and the code blocks for each clause
77690  * handle -all- alternatives for that first character. Ecmascript
77691  * specification uses the "longest match wins" semantics, so the order
77692  * of the if-clauses matters.
77693  *
77694  * Misc notes:
77695  *
77696  * * Ecmascript numeric literals do not accept a sign character.
77697  * Consequently e.g. "-1.0" is parsed as two tokens: a negative
77698  * sign and a positive numeric literal. The compiler performs
77699  * the negation during compilation, so this has no adverse impact.
77700  *
77701  * * There is no token for "undefined": it is just a value available
77702  * from the global object (or simply established by doing a reference
77703  * to an undefined value).
77704  *
77705  * * Some contexts want Identifier tokens, which are IdentifierNames
77706  * excluding reserved words, while some contexts want IdentifierNames
77707  * directly. In the latter case e.g. "while" is interpreted as an
77708  * identifier name, not a DUK_TOK_WHILE token. The solution here is
77709  * to provide both token types: DUK_TOK_WHILE goes to 't' while
77710  * DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
77711  * the identifier / keyword name.
77712  *
77713  * * Directive prologue needs to identify string literals such as
77714  * "use strict" and 'use strict', which are sensitive to line
77715  * continuations and escape sequences. For instance, "use\u0020strict"
77716  * is a valid directive but is distinct from "use strict". The solution
77717  * here is to decode escapes while tokenizing, but to keep track of the
77718  * number of escapes. Directive detection can then check that the
77719  * number of escapes is zero.
77720  *
77721  * * Multi-line comments with one or more internal LineTerminator are
77722  * treated like a line terminator to comply with automatic semicolon
77723  * insertion.
77724  */
77725 
77726 DUK_INTERNAL
77727 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
77728  duk_token *out_token,
77729  duk_bool_t strict_mode,
77730  duk_bool_t regexp_mode) {
77731  duk_codepoint_t x; /* temporary, must be signed and 32-bit to hold Unicode code points */
77732  duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
77733  * init is unnecessary but suppresses "may be used uninitialized" warnings.
77734  */
77735  duk_bool_t got_lineterm = 0; /* got lineterm preceding non-whitespace, non-lineterm token */
77736 
77737  if (++lex_ctx->token_count >= lex_ctx->token_limit) {
77738  goto fail_token_limit;
77739  }
77740 
77741  out_token->t = DUK_TOK_EOF;
77742  out_token->t_nores = -1; /* marker: copy t if not changed */
77743 #if 0 /* not necessary to init, disabled for faster parsing */
77744  out_token->num = DUK_DOUBLE_NAN;
77745  out_token->str1 = NULL;
77746  out_token->str2 = NULL;
77747 #endif
77748  out_token->num_escapes = 0;
77749  /* out_token->lineterm set by caller */
77750 
77751  /* This would be nice, but parsing is faster without resetting the
77752  * value slots. The only side effect is that references to temporary
77753  * string values may linger until lexing is finished; they're then
77754  * freed normally.
77755  */
77756 #if 0
77757  duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
77758  duk_to_undefined((duk_context *) lex_ctx->thr, lex_ctx->slot2_idx);
77759 #endif
77760 
77761  /* 'advtok' indicates how much to advance and which token id to assign
77762  * at the end. This shared functionality minimizes code size. All
77763  * code paths are required to set 'advtok' to some value, so no default
77764  * init value is used. Code paths calling DUK_ERROR() never return so
77765  * they don't need to set advtok.
77766  */
77767 
77768  /*
77769  * Matching order:
77770  *
77771  * Punctuator first chars, also covers comments, regexps
77772  * LineTerminator
77773  * Identifier or reserved word, also covers null/true/false literals
77774  * NumericLiteral
77775  * StringLiteral
77776  * EOF
77777  *
77778  * The order does not matter as long as the longest match is
77779  * always correctly identified. There are order dependencies
77780  * in the clauses, so it's not trivial to convert to a switch.
77781  */
77782 
77783  restart_lineupdate:
77784  out_token->start_line = lex_ctx->window[0].line;
77785 
77786  restart:
77787  out_token->start_offset = lex_ctx->window[0].offset;
77788 
77789  x = DUK__L0();
77790 
77791  switch (x) {
77792  case DUK_ASC_SPACE:
77793  case DUK_ASC_HT: /* fast paths for space and tab */
77794  DUK__ADVANCECHARS(lex_ctx, 1);
77795  goto restart;
77796  case DUK_ASC_LF: /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
77797  DUK__ADVANCECHARS(lex_ctx, 1);
77798  got_lineterm = 1;
77799  goto restart_lineupdate;
77800  case DUK_ASC_SLASH: /* '/' */
77801  if (DUK__L1() == DUK_ASC_SLASH) {
77802  /*
77803  * E5 Section 7.4, allow SourceCharacter (which is any 16-bit
77804  * code point).
77805  */
77806 
77807  /* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but it unnecessary */
77808  for (;;) {
77809  x = DUK__L0();
77810  if (x < 0 || duk_unicode_is_line_terminator(x)) {
77811  break;
77812  }
77813  DUK__ADVANCECHARS(lex_ctx, 1);
77814  }
77815  goto restart; /* line terminator will be handled on next round */
77816  } else if (DUK__L1() == DUK_ASC_STAR) {
77817  /*
77818  * E5 Section 7.4. If the multi-line comment contains a newline,
77819  * it is treated like a single line terminator for automatic
77820  * semicolon insertion.
77821  */
77822 
77823  duk_bool_t last_asterisk = 0;
77824  DUK__ADVANCECHARS(lex_ctx, 2);
77825  for (;;) {
77826  x = DUK__L0();
77827  if (x < 0) {
77828  goto fail_unterm_comment;
77829  }
77830  DUK__ADVANCECHARS(lex_ctx, 1);
77831  if (last_asterisk && x == DUK_ASC_SLASH) {
77832  break;
77833  }
77834  if (duk_unicode_is_line_terminator(x)) {
77835  got_lineterm = 1;
77836  }
77837  last_asterisk = (x == DUK_ASC_STAR);
77838  }
77839  goto restart_lineupdate;
77840  } else if (regexp_mode) {
77841 #if defined(DUK_USE_REGEXP_SUPPORT)
77842  /*
77843  * "/" followed by something in regexp mode. See E5 Section 7.8.5.
77844  *
77845  * RegExp parsing is a bit complex. First, the regexp body is delimited
77846  * by forward slashes, but the body may also contain forward slashes as
77847  * part of an escape sequence or inside a character class (delimited by
77848  * square brackets). A mini state machine is used to implement these.
77849  *
77850  * Further, an early (parse time) error must be thrown if the regexp
77851  * would cause a run-time error when used in the expression new RegExp(...).
77852  * Parsing here simply extracts the (candidate) regexp, and also accepts
77853  * invalid regular expressions (which are delimited properly). The caller
77854  * (compiler) must perform final validation and regexp compilation.
77855  *
77856  * RegExp first char may not be '/' (single line comment) or '*' (multi-
77857  * line comment). These have already been checked above, so there is no
77858  * need below for special handling of the first regexp character as in
77859  * the E5 productions.
77860  *
77861  * About unicode escapes within regexp literals:
77862  *
77863  * E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
77864  * However, Section 6 states that regexps accept the escapes,
77865  * see paragraph starting with "In string literals...".
77866  * The regexp grammar, which sees the decoded regexp literal
77867  * (after lexical parsing) DOES have a \uHHHH unicode escape.
77868  * So, for instance:
77869  *
77870  * /\u1234/
77871  *
77872  * should first be parsed by the lexical grammar as:
77873  *
77874  * '\' 'u' RegularExpressionBackslashSequence
77875  * '1' RegularExpressionNonTerminator
77876  * '2' RegularExpressionNonTerminator
77877  * '3' RegularExpressionNonTerminator
77878  * '4' RegularExpressionNonTerminator
77879  *
77880  * and the escape itself is then parsed by the regexp engine.
77881  * This is the current implementation.
77882  *
77883  * Minor spec inconsistency:
77884  *
77885  * E5 Section 7.8.5 RegularExpressionBackslashSequence is:
77886  *
77887  * \ RegularExpressionNonTerminator
77888  *
77889  * while Section A.1 RegularExpressionBackslashSequence is:
77890  *
77891  * \ NonTerminator
77892  *
77893  * The latter is not normative and a typo.
77894  *
77895  */
77896 
77897  /* first, parse regexp body roughly */
77898 
77899  duk_small_int_t state = 0; /* 0=base, 1=esc, 2=class, 3=class+esc */
77900 
77901  DUK__INITBUFFER(lex_ctx);
77902  for (;;) {
77903  DUK__ADVANCECHARS(lex_ctx, 1); /* skip opening slash on first loop */
77904  x = DUK__L0();
77905  if (x < 0 || duk_unicode_is_line_terminator(x)) {
77906  goto fail_unterm_regexp;
77907  }
77908  x = DUK__L0(); /* re-read to avoid spill / fetch */
77909  if (state == 0) {
77910  if (x == DUK_ASC_SLASH) {
77911  DUK__ADVANCECHARS(lex_ctx, 1); /* eat closing slash */
77912  break;
77913  } else if (x == DUK_ASC_BACKSLASH) {
77914  state = 1;
77915  } else if (x == DUK_ASC_LBRACKET) {
77916  state = 2;
77917  }
77918  } else if (state == 1) {
77919  state = 0;
77920  } else if (state == 2) {
77921  if (x == DUK_ASC_RBRACKET) {
77922  state = 0;
77923  } else if (x == DUK_ASC_BACKSLASH) {
77924  state = 3;
77925  }
77926  } else { /* state == 3 */
77927  state = 2;
77928  }
77929  DUK__APPENDBUFFER(lex_ctx, x);
77930  }
77931  out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
77932 
77933  /* second, parse flags */
77934 
77935  DUK__INITBUFFER(lex_ctx);
77936  for (;;) {
77937  x = DUK__L0();
77938  if (!duk_unicode_is_identifier_part(x)) {
77939  break;
77940  }
77941  x = DUK__L0(); /* re-read to avoid spill / fetch */
77942  DUK__APPENDBUFFER(lex_ctx, x);
77943  DUK__ADVANCECHARS(lex_ctx, 1);
77944  }
77945  out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
77946 
77947  DUK__INITBUFFER(lex_ctx); /* free some memory */
77948 
77949  /* validation of the regexp is caller's responsibility */
77950 
77951  advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
77952 #else /* DUK_USE_REGEXP_SUPPORT */
77953  goto fail_regexp_support;
77954 #endif /* DUK_USE_REGEXP_SUPPORT */
77955  } else if (DUK__L1() == DUK_ASC_EQUALS) {
77956  /* "/=" and not in regexp mode */
77957  advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
77958  } else {
77959  /* "/" and not in regexp mode */
77960  advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
77961  }
77962  break;
77963  case DUK_ASC_LCURLY: /* '{' */
77964  advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
77965  break;
77966  case DUK_ASC_RCURLY: /* '}' */
77967  advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
77968  break;
77969  case DUK_ASC_LPAREN: /* '(' */
77970  advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
77971  break;
77972  case DUK_ASC_RPAREN: /* ')' */
77973  advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
77974  break;
77975  case DUK_ASC_LBRACKET: /* '[' */
77976  advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
77977  break;
77978  case DUK_ASC_RBRACKET: /* ']' */
77979  advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
77980  break;
77981  case DUK_ASC_PERIOD: /* '.' */
77982  if (DUK__ISDIGIT(DUK__L1())) {
77983  /* Period followed by a digit can only start DecimalLiteral
77984  * (handled in slow path). We could jump straight into the
77985  * DecimalLiteral handling but should avoid goto to inside
77986  * a block.
77987  */
77988  goto slow_path;
77989  }
77990  advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
77991  break;
77992  case DUK_ASC_SEMICOLON: /* ';' */
77993  advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
77994  break;
77995  case DUK_ASC_COMMA: /* ',' */
77996  advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
77997  break;
77998  case DUK_ASC_LANGLE: /* '<' */
77999  if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
78000  advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
78001  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78002  advtok = DUK__ADVTOK(2, DUK_TOK_LE);
78003  } else if (DUK__L1() == DUK_ASC_LANGLE) {
78004  advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
78005  } else {
78006  advtok = DUK__ADVTOK(1, DUK_TOK_LT);
78007  }
78008  break;
78009  case DUK_ASC_RANGLE: /* '>' */
78010  if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
78011  advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
78012  } else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
78013  advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
78014  } else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
78015  advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
78016  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78017  advtok = DUK__ADVTOK(2, DUK_TOK_GE);
78018  } else if (DUK__L1() == DUK_ASC_RANGLE) {
78019  advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
78020  } else {
78021  advtok = DUK__ADVTOK(1, DUK_TOK_GT);
78022  }
78023  break;
78024  case DUK_ASC_EQUALS: /* '=' */
78025  if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
78026  advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
78027  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78028  advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
78029  } else {
78030  advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
78031  }
78032  break;
78033  case DUK_ASC_EXCLAMATION: /* '!' */
78034  if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
78035  advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
78036  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78037  advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
78038  } else {
78039  advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
78040  }
78041  break;
78042  case DUK_ASC_PLUS: /* '+' */
78043  if (DUK__L1() == DUK_ASC_PLUS) {
78044  advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
78045  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78046  advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
78047  } else {
78048  advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
78049  }
78050  break;
78051  case DUK_ASC_MINUS: /* '-' */
78052  if (DUK__L1() == DUK_ASC_MINUS) {
78053  advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
78054  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78055  advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
78056  } else {
78057  advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
78058  }
78059  break;
78060  case DUK_ASC_STAR: /* '*' */
78061 #if defined(DUK_USE_ES7_EXP_OPERATOR)
78062  if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
78063  advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
78064  } else if (DUK__L1() == DUK_ASC_STAR) {
78065  advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
78066  } else
78067 #endif
78068  if (DUK__L1() == DUK_ASC_EQUALS) {
78069  advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
78070  } else {
78071  advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
78072  }
78073  break;
78074  case DUK_ASC_PERCENT: /* '%' */
78075  if (DUK__L1() == DUK_ASC_EQUALS) {
78076  advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
78077  } else {
78078  advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
78079  }
78080  break;
78081  case DUK_ASC_AMP: /* '&' */
78082  if (DUK__L1() == DUK_ASC_AMP) {
78083  advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
78084  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78085  advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
78086  } else {
78087  advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
78088  }
78089  break;
78090  case DUK_ASC_PIPE: /* '|' */
78091  if (DUK__L1() == DUK_ASC_PIPE) {
78092  advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
78093  } else if (DUK__L1() == DUK_ASC_EQUALS) {
78094  advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
78095  } else {
78096  advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
78097  }
78098  break;
78099  case DUK_ASC_CARET: /* '^' */
78100  if (DUK__L1() == DUK_ASC_EQUALS) {
78101  advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
78102  } else {
78103  advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
78104  }
78105  break;
78106  case DUK_ASC_TILDE: /* '~' */
78107  advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
78108  break;
78109  case DUK_ASC_QUESTION: /* '?' */
78110  advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
78111  break;
78112  case DUK_ASC_COLON: /* ':' */
78113  advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
78114  break;
78115  case DUK_ASC_DOUBLEQUOTE: /* '"' */
78116  case DUK_ASC_SINGLEQUOTE: { /* '\'' */
78117  DUK__INITBUFFER(lex_ctx);
78118  duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
78119  duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
78120  out_token->str1 = duk_known_hstring((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
78121 
78122  DUK__INITBUFFER(lex_ctx); /* free some memory */
78123 
78124  advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
78125  break;
78126  }
78127  default:
78128  goto slow_path;
78129  } /* switch */
78130 
78131  goto skip_slow_path;
78132 
78133  slow_path:
78134  if (duk_unicode_is_line_terminator(x)) {
78135  if (x == 0x000d && DUK__L1() == 0x000a) {
78136  /*
78137  * E5 Section 7.3: CR LF is detected as a single line terminator for
78138  * line numbers. Here we also detect it as a single line terminator
78139  * token.
78140  */
78141  DUK__ADVANCECHARS(lex_ctx, 2);
78142  } else {
78143  DUK__ADVANCECHARS(lex_ctx, 1);
78144  }
78145  got_lineterm = 1;
78146  goto restart_lineupdate;
78147  } else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
78148  /*
78149  * Parse an identifier and then check whether it is:
78150  * - reserved word (keyword or other reserved word)
78151  * - "null" (NullLiteral)
78152  * - "true" (BooleanLiteral)
78153  * - "false" (BooleanLiteral)
78154  * - anything else => identifier
78155  *
78156  * This does not follow the E5 productions cleanly, but is
78157  * useful and compact.
78158  *
78159  * Note that identifiers may contain Unicode escapes,
78160  * see E5 Sections 6 and 7.6. They must be decoded first,
78161  * and the result checked against allowed characters.
78162  * The above if-clause accepts an identifier start and an
78163  * '\' character -- no other token can begin with a '\'.
78164  *
78165  * Note that "get" and "set" are not reserved words in E5
78166  * specification so they are recognized as plain identifiers
78167  * (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
78168  * used now). The compiler needs to work around this.
78169  *
78170  * Strictly speaking, following Ecmascript longest match
78171  * specification, an invalid escape for the first character
78172  * should cause a syntax error. However, an invalid escape
78173  * for IdentifierParts should just terminate the identifier
78174  * early (longest match), and let the next tokenization
78175  * fail. For instance Rhino croaks with 'foo\z' when
78176  * parsing the identifier. This has little practical impact.
78177  */
78178 
78179  duk_small_int_t i, i_end;
78180  duk_bool_t first = 1;
78181  duk_hstring *str;
78182 
78183  DUK__INITBUFFER(lex_ctx);
78184  for (;;) {
78185  /* re-lookup first char on first loop */
78186  if (DUK__L0() == DUK_ASC_BACKSLASH) {
78187  duk_codepoint_t esc_cp;
78188  if (DUK__L1() != DUK_ASC_LC_U) {
78189  goto fail_escape;
78190  }
78191  esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
78192  DUK__APPENDBUFFER(lex_ctx, esc_cp);
78193 
78194  /* IdentifierStart is stricter than IdentifierPart, so if the first
78195  * character is escaped, must have a stricter check here.
78196  */
78197  if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
78198  goto fail_escape;
78199  }
78200 
78201  /* Track number of escapes: necessary for proper keyword
78202  * detection.
78203  */
78204  out_token->num_escapes++;
78205  } else {
78206  /* Note: first character is checked against this. But because
78207  * IdentifierPart includes all IdentifierStart characters, and
78208  * the first character (if unescaped) has already been checked
78209  * in the if condition, this is OK.
78210  */
78211  if (!duk_unicode_is_identifier_part(DUK__L0())) {
78212  break;
78213  }
78214  DUK__APPENDBUFFER(lex_ctx, DUK__L0());
78215  DUK__ADVANCECHARS(lex_ctx, 1);
78216  }
78217  first = 0;
78218  }
78219 
78220  out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
78221  str = out_token->str1;
78222  out_token->t_nores = DUK_TOK_IDENTIFIER;
78223 
78224  DUK__INITBUFFER(lex_ctx); /* free some memory */
78225 
78226  /*
78227  * Interned identifier is compared against reserved words, which are
78228  * currently interned into the heap context. See genbuiltins.py.
78229  *
78230  * Note that an escape in the identifier disables recognition of
78231  * keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
78232  * identifier named "if"). This is not necessarily compliant,
78233  * see test-dec-escaped-char-in-keyword.js.
78234  *
78235  * Note: "get" and "set" are awkward. They are not officially
78236  * ReservedWords (and indeed e.g. "var set = 1;" is valid), and
78237  * must come out as DUK_TOK_IDENTIFIER. The compiler needs to
78238  * work around this a bit.
78239  */
78240 
78241  /* XXX: optimize by adding the token numbers directly into the
78242  * always interned duk_hstring objects (there should be enough
78243  * flag bits free for that)?
78244  */
78245 
78246  i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
78247 
78248  advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
78249  if (out_token->num_escapes == 0) {
78250  for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
78251  DUK_ASSERT(i >= 0 && i < DUK_HEAP_NUM_STRINGS);
78252  if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
78253  advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
78254  break;
78255  }
78256  }
78257  }
78258  } else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
78259  /* Note: decimal number may start with a period, but must be followed by a digit */
78260 
78261  /*
78262  * Pre-parsing for decimal, hex, octal (both legacy and ES2015),
78263  * and binary literals, followed by an actual parser step
78264  * provided by numconv.
78265  *
78266  * Note: the leading sign character ('+' or '-') is -not- part of
78267  * the production in E5 grammar, and that the a DecimalLiteral
78268  * starting with a '0' must be followed by a non-digit.
78269  *
78270  * XXX: the two step parsing process is quite awkward, it would
78271  * be more straightforward to allow numconv to parse the longest
78272  * valid prefix (it already does that, it only needs to indicate
78273  * where the input ended). However, the lexer decodes characters
78274  * using a limited lookup window, so this is not a trivial change.
78275  */
78276 
78277  /* XXX: because of the final check below (that the literal is not
78278  * followed by a digit), this could maybe be simplified, if we bail
78279  * out early from a leading zero (and if there are no periods etc).
78280  * Maybe too complex.
78281  */
78282 
78283  duk_double_t val;
78284  duk_bool_t legacy_oct = 0;
78285  duk_small_int_t state; /* 0=before period/exp,
78286  * 1=after period, before exp
78287  * 2=after exp, allow '+' or '-'
78288  * 3=after exp and exp sign
78289  */
78290  duk_small_uint_t s2n_flags;
78291  duk_codepoint_t y, z;
78292  duk_small_uint_t s2n_radix = 10;
78293  duk_small_uint_t pre_adv = 0;
78294 
78295  DUK__INITBUFFER(lex_ctx);
78296  y = DUK__L1();
78297 
78298  if (x == DUK_ASC_0) {
78299  z = DUK_LOWERCASE_CHAR_ASCII(y);
78300 
78301  pre_adv = 2; /* default for 0xNNN, 0oNNN, 0bNNN. */
78302  if (z == DUK_ASC_LC_X) {
78303  s2n_radix = 16;
78304  } else if (z == DUK_ASC_LC_O) {
78305  s2n_radix = 8;
78306  } else if (z == DUK_ASC_LC_B) {
78307  s2n_radix = 2;
78308  } else {
78309  pre_adv = 0;
78310  if (DUK__ISDIGIT(y)) {
78311  if (strict_mode) {
78312  /* Reject octal like \07 but also octal-lookalike
78313  * decimal like \08 in strict mode.
78314  */
78315  goto fail_number_literal;
78316  } else {
78317  /* Legacy OctalIntegerLiteral or octal-lookalice
78318  * decimal. Deciding between the two happens below
78319  * in digit scanning.
78320  */
78321  DUK__APPENDBUFFER(lex_ctx, x);
78322  pre_adv = 1;
78323  legacy_oct = 1;
78324  s2n_radix = 8; /* tentative unless conflicting digits found */
78325  }
78326  }
78327  }
78328  }
78329 
78330  DUK__ADVANCECHARS(lex_ctx, pre_adv);
78331 
78332  /* XXX: we could parse integers here directly, and fall back
78333  * to numconv only when encountering a fractional expression
78334  * or when an octal literal turned out to be decimal (0778 etc).
78335  */
78336  state = 0;
78337  for (;;) {
78338  x = DUK__L0(); /* re-lookup curr char on first round */
78339  if (DUK__ISDIGIT(x)) {
78340  /* Note: intentionally allow leading zeroes here, as the
78341  * actual parser will check for them.
78342  */
78343  if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
78344  /* Started out as an octal-lookalike
78345  * but interpreted as decimal, e.g.
78346  * '0779' -> 779. This also means
78347  * that fractions are allowed, e.g.
78348  * '0779.123' is allowed but '0777.123'
78349  * is not!
78350  */
78351  s2n_radix = 10;
78352  }
78353  if (state == 2) {
78354  state = 3;
78355  }
78356  } else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
78357  /* Note: 'e' and 'E' are also accepted here. */
78358  ;
78359  } else if (x == DUK_ASC_PERIOD) {
78360  if (state >= 1 || s2n_radix != 10) {
78361  break;
78362  } else {
78363  state = 1;
78364  }
78365  } else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
78366  if (state >= 2 || s2n_radix != 10) {
78367  break;
78368  } else {
78369  state = 2;
78370  }
78371  } else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
78372  if (state != 2) {
78373  break;
78374  } else {
78375  state = 3;
78376  }
78377  } else {
78378  break;
78379  }
78380  DUK__APPENDBUFFER(lex_ctx, x);
78381  DUK__ADVANCECHARS(lex_ctx, 1);
78382  }
78383 
78384  /* XXX: better coercion */
78385  (void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
78386 
78387  if (s2n_radix != 10) {
78388  /* For bases other than 10, integer only. */
78389  s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
78390  } else {
78391  s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
78392  DUK_S2N_FLAG_ALLOW_FRAC |
78393  DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
78394  DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
78395  DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
78396  }
78397 
78398  duk_dup((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx);
78399  duk_numconv_parse((duk_context *) lex_ctx->thr, s2n_radix, s2n_flags);
78400  val = duk_to_number_m1((duk_context *) lex_ctx->thr);
78401  if (DUK_ISNAN(val)) {
78402  goto fail_number_literal;
78403  }
78404  duk_replace((duk_context *) lex_ctx->thr, lex_ctx->slot1_idx); /* could also just pop? */
78405 
78406  DUK__INITBUFFER(lex_ctx); /* free some memory */
78407 
78408  /* Section 7.8.3 (note): NumericLiteral must be followed by something other than
78409  * IdentifierStart or DecimalDigit.
78410  */
78411 
78412  if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
78413  goto fail_number_literal;
78414  }
78415 
78416  out_token->num = val;
78417  advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
78418  } else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
78419  DUK__ADVANCECHARS(lex_ctx, 1);
78420  goto restart;
78421  } else if (x < 0) {
78422  advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
78423  } else {
78424  goto fail_token;
78425  }
78426  skip_slow_path:
78427 
78428  /*
78429  * Shared exit path
78430  */
78431 
78432  DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
78433  out_token->t = advtok & 0xff;
78434  if (out_token->t_nores < 0) {
78435  out_token->t_nores = out_token->t;
78436  }
78437  out_token->lineterm = got_lineterm;
78438 
78439  /* Automatic semicolon insertion is allowed if a token is preceded
78440  * by line terminator(s), or terminates a statement list (right curly
78441  * or EOF).
78442  */
78443  if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
78444  out_token->allow_auto_semi = 1;
78445  } else {
78446  out_token->allow_auto_semi = 0;
78447  }
78448 
78449  return;
78450 
78451  fail_token_limit:
78452  DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
78453  return;
78454 
78455  fail_token:
78456  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
78457  return;
78458 
78459  fail_number_literal:
78460  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
78461  return;
78462 
78463  fail_escape:
78464  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
78465  return;
78466 
78467  fail_unterm_regexp:
78468  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
78469  return;
78470 
78471  fail_unterm_comment:
78472  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
78473  return;
78474 
78475 #if !defined(DUK_USE_REGEXP_SUPPORT)
78476  fail_regexp_support:
78477  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
78478  return;
78479 #endif
78480 }
78481 
78482 #if defined(DUK_USE_REGEXP_SUPPORT)
78483 
78484 /*
78485  * Parse a RegExp token. The grammar is described in E5 Section 15.10.
78486  * Terminal constructions (such as quantifiers) are parsed directly here.
78487  *
78488  * 0xffffffffU is used as a marker for "infinity" in quantifiers. Further,
78489  * DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
78490  * will be accepted for a quantifier.
78491  */
78492 
78493 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
78494  duk_small_int_t advtok = 0; /* init is unnecessary but suppresses "may be used uninitialized" warnings */
78495  duk_codepoint_t x, y;
78496 
78497  if (++lex_ctx->token_count >= lex_ctx->token_limit) {
78498  goto fail_token_limit;
78499  }
78500 
78501  DUK_MEMZERO(out_token, sizeof(*out_token));
78502 
78503  x = DUK__L0();
78504  y = DUK__L1();
78505 
78506  DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
78507 
78508  switch (x) {
78509  case DUK_ASC_PIPE: {
78510  advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
78511  break;
78512  }
78513  case DUK_ASC_CARET: {
78514  advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
78515  break;
78516  }
78517  case DUK_ASC_DOLLAR: {
78518  advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
78519  break;
78520  }
78521  case DUK_ASC_QUESTION: {
78522  out_token->qmin = 0;
78523  out_token->qmax = 1;
78524  if (y == DUK_ASC_QUESTION) {
78525  advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
78526  out_token->greedy = 0;
78527  } else {
78528  advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
78529  out_token->greedy = 1;
78530  }
78531  break;
78532  }
78533  case DUK_ASC_STAR: {
78534  out_token->qmin = 0;
78535  out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
78536  if (y == DUK_ASC_QUESTION) {
78537  advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
78538  out_token->greedy = 0;
78539  } else {
78540  advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
78541  out_token->greedy = 1;
78542  }
78543  break;
78544  }
78545  case DUK_ASC_PLUS: {
78546  out_token->qmin = 1;
78547  out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
78548  if (y == DUK_ASC_QUESTION) {
78549  advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
78550  out_token->greedy = 0;
78551  } else {
78552  advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
78553  out_token->greedy = 1;
78554  }
78555  break;
78556  }
78557  case DUK_ASC_LCURLY: {
78558  /* Production allows 'DecimalDigits', including leading zeroes */
78559  duk_uint_fast32_t val1 = 0;
78560  duk_uint_fast32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
78561  duk_small_int_t digits = 0;
78562 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
78563  duk_lexer_point lex_pt;
78564 #endif
78565 
78566 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
78567  /* Store lexer position, restoring if quantifier is invalid. */
78568  DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
78569 #endif
78570 
78571  for (;;) {
78572  DUK__ADVANCECHARS(lex_ctx, 1); /* eat '{' on entry */
78573  x = DUK__L0();
78574  if (DUK__ISDIGIT(x)) {
78575  digits++;
78576  val1 = val1 * 10 + (duk_uint_fast32_t) duk__hexval(x);
78577  } else if (x == DUK_ASC_COMMA) {
78578  if (digits > DUK__MAX_RE_QUANT_DIGITS) {
78579  goto invalid_quantifier;
78580  }
78581  if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
78582  goto invalid_quantifier;
78583  }
78584  if (DUK__L1() == DUK_ASC_RCURLY) {
78585  /* form: { DecimalDigits , }, val1 = min count */
78586  if (digits == 0) {
78587  goto invalid_quantifier;
78588  }
78589  out_token->qmin = val1;
78590  out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
78591  DUK__ADVANCECHARS(lex_ctx, 2);
78592  break;
78593  }
78594  val2 = val1;
78595  val1 = 0;
78596  digits = 0; /* not strictly necessary because of lookahead '}' above */
78597  } else if (x == DUK_ASC_RCURLY) {
78598  if (digits > DUK__MAX_RE_QUANT_DIGITS) {
78599  goto invalid_quantifier;
78600  }
78601  if (digits == 0) {
78602  goto invalid_quantifier;
78603  }
78604  if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
78605  /* val2 = min count, val1 = max count */
78606  out_token->qmin = val2;
78607  out_token->qmax = val1;
78608  } else {
78609  /* val1 = count */
78610  out_token->qmin = val1;
78611  out_token->qmax = val1;
78612  }
78613  DUK__ADVANCECHARS(lex_ctx, 1);
78614  break;
78615  } else {
78616  goto invalid_quantifier;
78617  }
78618  }
78619  if (DUK__L0() == DUK_ASC_QUESTION) {
78620  out_token->greedy = 0;
78621  DUK__ADVANCECHARS(lex_ctx, 1);
78622  } else {
78623  out_token->greedy = 1;
78624  }
78625  advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
78626  break;
78627  invalid_quantifier:
78628 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
78629  /* Failed to match the quantifier, restore lexer and parse
78630  * opening brace as a literal.
78631  */
78632  DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
78633  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
78634  out_token->num = DUK_ASC_LCURLY;
78635 #else
78636  goto fail_quantifier;
78637 #endif
78638  break;
78639  }
78640  case DUK_ASC_PERIOD: {
78641  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
78642  break;
78643  }
78644  case DUK_ASC_BACKSLASH: {
78645  /* The E5.1 specification does not seem to allow IdentifierPart characters
78646  * to be used as identity escapes. Unfortunately this includes '$', which
78647  * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
78648  * Many other implementations (including V8 and Rhino, for instance) do
78649  * accept '\$' as a valid identity escape, which is quite pragmatic, and
78650  * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
78651  */
78652 
78653  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR); /* default: char escape (two chars) */
78654  if (y == DUK_ASC_LC_B) {
78655  advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
78656  } else if (y == DUK_ASC_UC_B) {
78657  advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
78658  } else if (y == DUK_ASC_LC_F) {
78659  out_token->num = 0x000c;
78660  } else if (y == DUK_ASC_LC_N) {
78661  out_token->num = 0x000a;
78662  } else if (y == DUK_ASC_LC_T) {
78663  out_token->num = 0x0009;
78664  } else if (y == DUK_ASC_LC_R) {
78665  out_token->num = 0x000d;
78666  } else if (y == DUK_ASC_LC_V) {
78667  out_token->num = 0x000b;
78668  } else if (y == DUK_ASC_LC_C) {
78669  x = DUK__L2();
78670  if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
78671  (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
78672  out_token->num = (x % 32);
78673  advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
78674  } else {
78675  goto fail_escape;
78676  }
78677  } else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
78678  /* The token value is the Unicode codepoint without
78679  * it being decode into surrogate pair characters
78680  * here. The \u{H+} is only allowed in Unicode mode
78681  * which we don't support yet.
78682  */
78683  out_token->num = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
78684  advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
78685  } else if (y == DUK_ASC_LC_D) {
78686  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
78687  } else if (y == DUK_ASC_UC_D) {
78688  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
78689  } else if (y == DUK_ASC_LC_S) {
78690  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
78691  } else if (y == DUK_ASC_UC_S) {
78692  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
78693  } else if (y == DUK_ASC_LC_W) {
78694  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
78695  } else if (y == DUK_ASC_UC_W) {
78696  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
78697  } else if (DUK__ISDIGIT(y)) {
78698  /* E5 Section 15.10.2.11 */
78699  if (y == DUK_ASC_0) {
78700  if (DUK__ISDIGIT(DUK__L2())) {
78701  goto fail_escape;
78702  }
78703  out_token->num = 0x0000;
78704  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
78705  } else {
78706  /* XXX: shared parsing? */
78707  duk_uint_fast32_t val = 0;
78708  duk_small_int_t i;
78709  for (i = 0; ; i++) {
78710  if (i >= DUK__MAX_RE_DECESC_DIGITS) {
78711  goto fail_escape;
78712  }
78713  DUK__ADVANCECHARS(lex_ctx, 1); /* eat backslash on entry */
78714  x = DUK__L0();
78715  if (!DUK__ISDIGIT(x)) {
78716  break;
78717  }
78718  val = val * 10 + (duk_uint_fast32_t) duk__hexval(x);
78719  }
78720  /* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
78721  advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
78722  out_token->num = val;
78723  }
78724 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
78725  } else if (y >= 0) {
78726  /* For ES2015 Annex B, accept any source character as identity
78727  * escape except 'c' which is used for control characters.
78728  * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
78729  * Careful not to match end-of-buffer (<0) here.
78730  * This is not yet full ES2015 Annex B because cases above
78731  * (like hex escape) won't backtrack.
78732  */
78733  DUK_ASSERT(y != DUK_ASC_LC_C); /* covered above */
78734 #else /* DUK_USE_ES6_REGEXP_SYNTAX */
78735  } else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
78736  y == DUK_UNICODE_CP_ZWNJ ||
78737  y == DUK_UNICODE_CP_ZWJ) {
78738  /* For ES5.1 identity escapes are not allowed for identifier
78739  * parts. This conflicts with a lot of real world code as this
78740  * doesn't e.g. allow escaping a dollar sign as /\$/, see
78741  * test-regexp-identity-escape-dollar.js.
78742  */
78743 #endif /* DUK_USE_ES6_REGEXP_SYNTAX */
78744  out_token->num = y;
78745  } else {
78746  goto fail_escape;
78747  }
78748  break;
78749  }
78750  case DUK_ASC_LPAREN: {
78751  /* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
78752 
78753  if (y == DUK_ASC_QUESTION) {
78754  if (DUK__L2() == DUK_ASC_EQUALS) {
78755  /* (?= */
78756  advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
78757  } else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
78758  /* (?! */
78759  advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
78760  } else if (DUK__L2() == DUK_ASC_COLON) {
78761  /* (?: */
78762  advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
78763  }
78764  } else {
78765  /* ( */
78766  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
78767  }
78768  break;
78769  }
78770  case DUK_ASC_RPAREN: {
78771  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
78772  break;
78773  }
78774  case DUK_ASC_LBRACKET: {
78775  /*
78776  * To avoid creating a heavy intermediate value for the list of ranges,
78777  * only the start token ('[' or '[^') is parsed here. The regexp
78778  * compiler parses the ranges itself.
78779  */
78780 
78781  /* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
78782  * literal too, but it's not easy to parse without backtracking.
78783  */
78784 
78785  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
78786  if (y == DUK_ASC_CARET) {
78787  advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
78788  }
78789  break;
78790  }
78791 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
78792  case DUK_ASC_RCURLY:
78793  case DUK_ASC_RBRACKET: {
78794  /* Although these could be parsed as PatternCharacters unambiguously (here),
78795  * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
78796  */
78797  goto fail_invalid_char;
78798  break;
78799  }
78800 #endif
78801  case -1: {
78802  /* EOF */
78803  advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
78804  break;
78805  }
78806  default: {
78807  /* PatternCharacter, all excluded characters are matched by cases above */
78808  advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
78809  out_token->num = x;
78810  break;
78811  }
78812  }
78813 
78814  /*
78815  * Shared exit path
78816  */
78817 
78818  DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
78819  out_token->t = advtok & 0xff;
78820  return;
78821 
78822  fail_token_limit:
78823  DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
78824  return;
78825 
78826  fail_escape:
78827  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
78828  return;
78829 
78830 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
78831  fail_invalid_char:
78832  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
78833  return;
78834 
78835  fail_quantifier:
78836  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
78837  return;
78838 #endif
78839 }
78840 
78841 /*
78842  * Special parser for character classes; calls callback for every
78843  * range parsed and returns the number of ranges present.
78844  */
78845 
78846 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
78847  * required anyway. We could use that BUT we need to update the regexp compiler
78848  * 'nranges' too. Work this out a bit more cleanly to save space.
78849  */
78850 
78851 /* XXX: the handling of character range detection is a bit convoluted.
78852  * Try to simplify and make smaller.
78853  */
78854 
78855 /* XXX: logic for handling character ranges is now incorrect, it will accept
78856  * e.g. [\d-z] whereas it should croak from it? SMJS accepts this too, though.
78857  *
78858  * Needs a read through and a lot of additional tests.
78859  */
78860 
78861 DUK_LOCAL
78862 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
78863  duk_re_range_callback gen_range,
78864  void *userdata,
78865  const duk_uint16_t *ranges,
78866  duk_small_int_t num) {
78867  const duk_uint16_t *ranges_end;
78868 
78869  DUK_UNREF(lex_ctx);
78870 
78871  ranges_end = ranges + num;
78872  while (ranges < ranges_end) {
78873  /* mark range 'direct', bypass canonicalization (see Wiki) */
78874  gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
78875  ranges += 2;
78876  }
78877 }
78878 
78879 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
78880  duk_codepoint_t start = -1;
78881  duk_codepoint_t ch;
78882  duk_codepoint_t x;
78883  duk_bool_t dash = 0;
78884  duk_small_int_t adv = 0;
78885 
78886  DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
78887 
78888  for (;;) {
78889  DUK__ADVANCECHARS(lex_ctx, adv);
78890  adv = 1;
78891 
78892  x = DUK__L0();
78893 
78894  ch = -1; /* not strictly necessary, but avoids "uninitialized variable" warnings */
78895  DUK_UNREF(ch);
78896 
78897  if (x < 0) {
78898  goto fail_unterm_charclass;
78899  } else if (x == DUK_ASC_RBRACKET) {
78900  if (start >= 0) {
78901  gen_range(userdata, start, start, 0);
78902  }
78903  DUK__ADVANCECHARS(lex_ctx, 1); /* eat ']' before finishing */
78904  break;
78905  } else if (x == DUK_ASC_MINUS) {
78906  if (start >= 0 && !dash && DUK__L0() != DUK_ASC_RBRACKET) {
78907  /* '-' as a range indicator */
78908  dash = 1;
78909  continue;
78910  } else {
78911  /* '-' verbatim */
78912  ch = x;
78913  }
78914  } else if (x == DUK_ASC_BACKSLASH) {
78915  /*
78916  * The escapes are same as outside a character class, except that \b has a
78917  * different meaning, and \B and backreferences are prohibited (see E5
78918  * Section 15.10.2.19). However, it's difficult to share code because we
78919  * handle e.g. "\n" very differently: here we generate a single character
78920  * range for it.
78921  */
78922 
78923  /* XXX: ES2015 surrogate pair handling. */
78924 
78925  x = DUK__L1();
78926 
78927  adv = 2;
78928 
78929  if (x == DUK_ASC_LC_B) {
78930  /* Note: '\b' in char class is different than outside (assertion),
78931  * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
78932  * check below.
78933  */
78934  ch = 0x0008;
78935  } else if (x == DUK_ASC_LC_F) {
78936  ch = 0x000c;
78937  } else if (x == DUK_ASC_LC_N) {
78938  ch = 0x000a;
78939  } else if (x == DUK_ASC_LC_T) {
78940  ch = 0x0009;
78941  } else if (x == DUK_ASC_LC_R) {
78942  ch = 0x000d;
78943  } else if (x == DUK_ASC_LC_V) {
78944  ch = 0x000b;
78945  } else if (x == DUK_ASC_LC_C) {
78946  x = DUK__L2();
78947  adv = 3;
78948  if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
78949  (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
78950  ch = (x % 32);
78951  } else {
78952  goto fail_escape;
78953  }
78954  } else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
78955  /* The \u{H+} form is only allowed in Unicode mode which
78956  * we don't support yet.
78957  */
78958  ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
78959  adv = 0;
78960  } else if (x == DUK_ASC_LC_D) {
78961  duk__emit_u16_direct_ranges(lex_ctx,
78962  gen_range,
78963  userdata,
78964  duk_unicode_re_ranges_digit,
78965  sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
78966  ch = -1;
78967  } else if (x == DUK_ASC_UC_D) {
78968  duk__emit_u16_direct_ranges(lex_ctx,
78969  gen_range,
78970  userdata,
78971  duk_unicode_re_ranges_not_digit,
78972  sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
78973  ch = -1;
78974  } else if (x == DUK_ASC_LC_S) {
78975  duk__emit_u16_direct_ranges(lex_ctx,
78976  gen_range,
78977  userdata,
78978  duk_unicode_re_ranges_white,
78979  sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
78980  ch = -1;
78981  } else if (x == DUK_ASC_UC_S) {
78982  duk__emit_u16_direct_ranges(lex_ctx,
78983  gen_range,
78984  userdata,
78985  duk_unicode_re_ranges_not_white,
78986  sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
78987  ch = -1;
78988  } else if (x == DUK_ASC_LC_W) {
78989  duk__emit_u16_direct_ranges(lex_ctx,
78990  gen_range,
78991  userdata,
78992  duk_unicode_re_ranges_wordchar,
78993  sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
78994  ch = -1;
78995  } else if (x == DUK_ASC_UC_W) {
78996  duk__emit_u16_direct_ranges(lex_ctx,
78997  gen_range,
78998  userdata,
78999  duk_unicode_re_ranges_not_wordchar,
79000  sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
79001  ch = -1;
79002  } else if (DUK__ISDIGIT(x)) {
79003  /* DecimalEscape, only \0 is allowed, no leading zeroes are allowed */
79004  if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
79005  ch = 0x0000;
79006  } else {
79007  goto fail_escape;
79008  }
79009 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
79010  } else if (x >= 0) {
79011  /* IdentityEscape: ES2015 Annex B allows almost all
79012  * source characters here. Match anything except
79013  * EOF here.
79014  */
79015  ch = x;
79016 #else /* DUK_USE_ES6_REGEXP_SYNTAX */
79017  } else if (!duk_unicode_is_identifier_part(x)) {
79018  /* IdentityEscape: ES5.1 doesn't allow identity escape
79019  * for identifier part characters, which conflicts with
79020  * some real world code. For example, it doesn't allow
79021  * /[\$]/ which is awkward.
79022  */
79023  ch = x;
79024 #endif /* DUK_USE_ES6_REGEXP_SYNTAX */
79025  } else {
79026  goto fail_escape;
79027  }
79028  } else {
79029  /* character represents itself */
79030  ch = x;
79031  }
79032 
79033  /* ch is a literal character here or -1 if parsed entity was
79034  * an escape such as "\s".
79035  */
79036 
79037  if (ch < 0) {
79038  /* multi-character sets not allowed as part of ranges, see
79039  * E5 Section 15.10.2.15, abstract operation CharacterRange.
79040  */
79041  if (start >= 0) {
79042  if (dash) {
79043  goto fail_range;
79044  } else {
79045  gen_range(userdata, start, start, 0);
79046  start = -1;
79047  /* dash is already 0 */
79048  }
79049  }
79050  } else {
79051  if (start >= 0) {
79052  if (dash) {
79053  if (start > ch) {
79054  goto fail_range;
79055  }
79056  gen_range(userdata, start, ch, 0);
79057  start = -1;
79058  dash = 0;
79059  } else {
79060  gen_range(userdata, start, start, 0);
79061  start = ch;
79062  /* dash is already 0 */
79063  }
79064  } else {
79065  start = ch;
79066  }
79067  }
79068  }
79069 
79070  return;
79071 
79072  fail_escape:
79073  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
79074  return;
79075 
79076  fail_range:
79077  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
79078  return;
79079 
79080  fail_unterm_charclass:
79081  DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
79082  return;
79083 }
79084 
79085 #endif /* DUK_USE_REGEXP_SUPPORT */
79086 
79087 /* automatic undefs */
79088 #undef DUK__ADVANCEBYTES
79089 #undef DUK__ADVANCECHARS
79090 #undef DUK__ADVTOK
79091 #undef DUK__APPENDBUFFER
79092 #undef DUK__APPENDBUFFER_ASCII
79093 #undef DUK__INITBUFFER
79094 #undef DUK__ISDIGIT
79095 #undef DUK__ISDIGIT03
79096 #undef DUK__ISDIGIT47
79097 #undef DUK__ISHEXDIGIT
79098 #undef DUK__ISOCTDIGIT
79099 #undef DUK__L0
79100 #undef DUK__L1
79101 #undef DUK__L2
79102 #undef DUK__L3
79103 #undef DUK__L4
79104 #undef DUK__L5
79105 #undef DUK__LOOKUP
79106 #undef DUK__MAX_RE_DECESC_DIGITS
79107 #undef DUK__MAX_RE_QUANT_DIGITS
79108 /*
79109  * Number-to-string and string-to-number conversions.
79110  *
79111  * Slow path number-to-string and string-to-number conversion is based on
79112  * a Dragon4 variant, with fast paths for small integers. Big integer
79113  * arithmetic is needed for guaranteeing that the conversion is correct
79114  * and uses a minimum number of digits. The big number arithmetic has a
79115  * fixed maximum size and does not require dynamic allocations.
79116  *
79117  * See: doc/number-conversion.rst.
79118  */
79119 
79120 /* #include duk_internal.h -> already included */
79121 
79122 #define DUK__IEEE_DOUBLE_EXP_BIAS 1023
79123 #define DUK__IEEE_DOUBLE_EXP_MIN (-1022) /* biased exp == 0 -> denormal, exp -1022 */
79124 
79125 #define DUK__DIGITCHAR(x) duk_lc_digits[(x)]
79126 
79127 /*
79128  * Tables generated with util/gennumdigits.py.
79129  *
79130  * duk__str2num_digits_for_radix indicates, for each radix, how many input
79131  * digits should be considered significant for string-to-number conversion.
79132  * The input is also padded to this many digits to give the Dragon4
79133  * conversion enough (apparent) precision to work with.
79134  *
79135  * duk__str2num_exp_limits indicates, for each radix, the radix-specific
79136  * minimum/maximum exponent values (for a Dragon4 integer mantissa)
79137  * below and above which the number is guaranteed to underflow to zero
79138  * or overflow to Infinity. This allows parsing to keep bigint values
79139  * bounded.
79140  */
79141 
79142 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
79143  69, 44, 35, 30, 27, 25, 23, 22, 20, 20, /* 2 to 11 */
79144  20, 19, 19, 18, 18, 17, 17, 17, 16, 16, /* 12 to 21 */
79145  16, 16, 16, 15, 15, 15, 15, 15, 15, 14, /* 22 to 31 */
79146  14, 14, 14, 14, 14 /* 31 to 36 */
79147 };
79148 
79149 typedef struct {
79150  duk_int16_t upper;
79151  duk_int16_t lower;
79152 } duk__exp_limits;
79153 
79154 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
79155  { 957, -1147 }, { 605, -725 }, { 479, -575 }, { 414, -496 },
79156  { 372, -446 }, { 342, -411 }, { 321, -384 }, { 304, -364 },
79157  { 291, -346 }, { 279, -334 }, { 268, -323 }, { 260, -312 },
79158  { 252, -304 }, { 247, -296 }, { 240, -289 }, { 236, -283 },
79159  { 231, -278 }, { 227, -273 }, { 223, -267 }, { 220, -263 },
79160  { 216, -260 }, { 213, -256 }, { 210, -253 }, { 208, -249 },
79161  { 205, -246 }, { 203, -244 }, { 201, -241 }, { 198, -239 },
79162  { 196, -237 }, { 195, -234 }, { 193, -232 }, { 191, -230 },
79163  { 190, -228 }, { 188, -226 }, { 187, -225 },
79164 };
79165 
79166 /*
79167  * Limited functionality bigint implementation.
79168  *
79169  * Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
79170  * with the caller responsible for ensuring this is never exceeded. No memory
79171  * allocation (except stack) is needed for bigint computation. Operations
79172  * have been tailored for number conversion needs.
79173  *
79174  * Argument order is "assignment order", i.e. target first, then arguments:
79175  * x <- y * z --> duk__bi_mul(x, y, z);
79176  */
79177 
79178 /* This upper value has been experimentally determined; debug build will check
79179  * bigint size with assertions.
79180  */
79181 #define DUK__BI_MAX_PARTS 37 /* 37x32 = 1184 bits */
79182 
79183 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
79184 #define DUK__BI_PRINT(name,x) duk__bi_print((name),(x))
79185 #else
79186 #define DUK__BI_PRINT(name,x)
79187 #endif
79188 
79189 /* Current size is about 152 bytes. */
79190 typedef struct {
79191  duk_small_int_t n;
79192  duk_uint32_t v[DUK__BI_MAX_PARTS]; /* low to high */
79193 } duk__bigint;
79194 
79195 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
79196 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
79197  /* Overestimate required size; debug code so not critical to be tight. */
79198  char buf[DUK__BI_MAX_PARTS * 9 + 64];
79199  char *p = buf;
79200  duk_small_int_t i;
79201 
79202  /* No NUL term checks in this debug code. */
79203  p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
79204  if (x->n == 0) {
79205  p += DUK_SPRINTF(p, " 0");
79206  }
79207  for (i = x->n - 1; i >= 0; i--) {
79208  p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
79209  }
79210 
79211  DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
79212 }
79213 #endif
79214 
79215 #if defined(DUK_USE_ASSERTIONS)
79216 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
79217  return (duk_small_int_t)
79218  ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
79219  ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
79220 }
79221 #endif
79222 
79223 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
79224  duk_small_int_t i;
79225 
79226  for (i = x->n - 1; i >= 0; i--) {
79227  if (x->v[i] != 0) {
79228  break;
79229  }
79230  }
79231 
79232  /* Note: if 'x' is zero, x->n becomes 0 here */
79233  x->n = i + 1;
79234  DUK_ASSERT(duk__bi_is_valid(x));
79235 }
79236 
79237 /* x <- y */
79238 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
79239  duk_small_int_t n;
79240 
79241  n = y->n;
79242  x->n = n;
79243  if (n == 0) {
79244  return;
79245  }
79246  DUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * n));
79247 }
79248 
79249 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
79250  if (v == 0U) {
79251  x->n = 0;
79252  } else {
79253  x->n = 1;
79254  x->v[0] = v;
79255  }
79256  DUK_ASSERT(duk__bi_is_valid(x));
79257 }
79258 
79259 /* Return value: <0 <=> x < y
79260  * 0 <=> x == y
79261  * >0 <=> x > y
79262  */
79263 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
79264  duk_small_int_t i, nx, ny;
79265  duk_uint32_t tx, ty;
79266 
79267  DUK_ASSERT(duk__bi_is_valid(x));
79268  DUK_ASSERT(duk__bi_is_valid(y));
79269 
79270  nx = x->n;
79271  ny = y->n;
79272  if (nx > ny) {
79273  goto ret_gt;
79274  }
79275  if (nx < ny) {
79276  goto ret_lt;
79277  }
79278  for (i = nx - 1; i >= 0; i--) {
79279  tx = x->v[i];
79280  ty = y->v[i];
79281 
79282  if (tx > ty) {
79283  goto ret_gt;
79284  }
79285  if (tx < ty) {
79286  goto ret_lt;
79287  }
79288  }
79289 
79290  return 0;
79291 
79292  ret_gt:
79293  return 1;
79294 
79295  ret_lt:
79296  return -1;
79297 }
79298 
79299 /* x <- y + z */
79300 #if defined(DUK_USE_64BIT_OPS)
79301 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
79302  duk_uint64_t tmp;
79303  duk_small_int_t i, ny, nz;
79304 
79305  DUK_ASSERT(duk__bi_is_valid(y));
79306  DUK_ASSERT(duk__bi_is_valid(z));
79307 
79308  if (z->n > y->n) {
79309  duk__bigint *t;
79310  t = y; y = z; z = t;
79311  }
79312  DUK_ASSERT(y->n >= z->n);
79313 
79314  ny = y->n; nz = z->n;
79315  tmp = 0U;
79316  for (i = 0; i < ny; i++) {
79317  DUK_ASSERT(i < DUK__BI_MAX_PARTS);
79318  tmp += y->v[i];
79319  if (i < nz) {
79320  tmp += z->v[i];
79321  }
79322  x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
79323  tmp = tmp >> 32;
79324  }
79325  if (tmp != 0U) {
79326  DUK_ASSERT(i < DUK__BI_MAX_PARTS);
79327  x->v[i++] = (duk_uint32_t) tmp;
79328  }
79329  x->n = i;
79330  DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
79331 
79332  /* no need to normalize */
79333  DUK_ASSERT(duk__bi_is_valid(x));
79334 }
79335 #else /* DUK_USE_64BIT_OPS */
79336 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
79337  duk_uint32_t carry, tmp1, tmp2;
79338  duk_small_int_t i, ny, nz;
79339 
79340  DUK_ASSERT(duk__bi_is_valid(y));
79341  DUK_ASSERT(duk__bi_is_valid(z));
79342 
79343  if (z->n > y->n) {
79344  duk__bigint *t;
79345  t = y; y = z; z = t;
79346  }
79347  DUK_ASSERT(y->n >= z->n);
79348 
79349  ny = y->n; nz = z->n;
79350  carry = 0U;
79351  for (i = 0; i < ny; i++) {
79352  /* Carry is detected based on wrapping which relies on exact 32-bit
79353  * types.
79354  */
79355  DUK_ASSERT(i < DUK__BI_MAX_PARTS);
79356  tmp1 = y->v[i];
79357  tmp2 = tmp1;
79358  if (i < nz) {
79359  tmp2 += z->v[i];
79360  }
79361 
79362  /* Careful with carry condition:
79363  * - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
79364  * - If carry added: 0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
79365  */
79366  if (carry) {
79367  tmp2++;
79368  carry = (tmp2 <= tmp1 ? 1U : 0U);
79369  } else {
79370  carry = (tmp2 < tmp1 ? 1U : 0U);
79371  }
79372 
79373  x->v[i] = tmp2;
79374  }
79375  if (carry) {
79376  DUK_ASSERT(i < DUK__BI_MAX_PARTS);
79377  DUK_ASSERT(carry == 1U);
79378  x->v[i++] = carry;
79379  }
79380  x->n = i;
79381  DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
79382 
79383  /* no need to normalize */
79384  DUK_ASSERT(duk__bi_is_valid(x));
79385 }
79386 #endif /* DUK_USE_64BIT_OPS */
79387 
79388 /* x <- y + z */
79389 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
79390  duk__bigint tmp;
79391 
79392  DUK_ASSERT(duk__bi_is_valid(y));
79393 
79394  /* XXX: this could be optimized; there is only one call site now though */
79395  duk__bi_set_small(&tmp, z);
79396  duk__bi_add(x, y, &tmp);
79397 
79398  DUK_ASSERT(duk__bi_is_valid(x));
79399 }
79400 
79401 #if 0 /* unused */
79402 /* x <- x + y, use t as temp */
79403 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
79404  duk__bi_add(t, x, y);
79405  duk__bi_copy(x, t);
79406 }
79407 #endif
79408 
79409 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
79410 #if defined(DUK_USE_64BIT_OPS)
79411 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
79412  duk_small_int_t i, ny, nz;
79413  duk_uint32_t ty, tz;
79414  duk_int64_t tmp;
79415 
79416  DUK_ASSERT(duk__bi_is_valid(y));
79417  DUK_ASSERT(duk__bi_is_valid(z));
79418  DUK_ASSERT(duk__bi_compare(y, z) >= 0);
79419  DUK_ASSERT(y->n >= z->n);
79420 
79421  ny = y->n; nz = z->n;
79422  tmp = 0;
79423  for (i = 0; i < ny; i++) {
79424  ty = y->v[i];
79425  if (i < nz) {
79426  tz = z->v[i];
79427  } else {
79428  tz = 0;
79429  }
79430  tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
79431  x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
79432  tmp = tmp >> 32; /* 0 or -1 */
79433  }
79434  DUK_ASSERT(tmp == 0);
79435 
79436  x->n = i;
79437  duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
79438  DUK_ASSERT(duk__bi_is_valid(x));
79439 }
79440 #else
79441 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
79442  duk_small_int_t i, ny, nz;
79443  duk_uint32_t tmp1, tmp2, borrow;
79444 
79445  DUK_ASSERT(duk__bi_is_valid(y));
79446  DUK_ASSERT(duk__bi_is_valid(z));
79447  DUK_ASSERT(duk__bi_compare(y, z) >= 0);
79448  DUK_ASSERT(y->n >= z->n);
79449 
79450  ny = y->n; nz = z->n;
79451  borrow = 0U;
79452  for (i = 0; i < ny; i++) {
79453  /* Borrow is detected based on wrapping which relies on exact 32-bit
79454  * types.
79455  */
79456  tmp1 = y->v[i];
79457  tmp2 = tmp1;
79458  if (i < nz) {
79459  tmp2 -= z->v[i];
79460  }
79461 
79462  /* Careful with borrow condition:
79463  * - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
79464  * - If borrow subtracted: 0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
79465  */
79466  if (borrow) {
79467  tmp2--;
79468  borrow = (tmp2 >= tmp1 ? 1U : 0U);
79469  } else {
79470  borrow = (tmp2 > tmp1 ? 1U : 0U);
79471  }
79472 
79473  x->v[i] = tmp2;
79474  }
79475  DUK_ASSERT(borrow == 0U);
79476 
79477  x->n = i;
79478  duk__bi_normalize(x); /* need to normalize, may even cancel to 0 */
79479  DUK_ASSERT(duk__bi_is_valid(x));
79480 }
79481 #endif
79482 
79483 #if 0 /* unused */
79484 /* x <- y - z */
79485 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
79486  duk__bigint tmp;
79487 
79488  DUK_ASSERT(duk__bi_is_valid(y));
79489 
79490  /* XXX: this could be optimized */
79491  duk__bi_set_small(&tmp, z);
79492  duk__bi_sub(x, y, &tmp);
79493 
79494  DUK_ASSERT(duk__bi_is_valid(x));
79495 }
79496 #endif
79497 
79498 /* x <- x - y, use t as temp */
79499 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
79500  duk__bi_sub(t, x, y);
79501  duk__bi_copy(x, t);
79502 }
79503 
79504 /* x <- y * z */
79505 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
79506  duk_small_int_t i, j, nx, nz;
79507 
79508  DUK_ASSERT(duk__bi_is_valid(y));
79509  DUK_ASSERT(duk__bi_is_valid(z));
79510 
79511  nx = y->n + z->n; /* max possible */
79512  DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
79513 
79514  if (nx == 0) {
79515  /* Both inputs are zero; cases where only one is zero can go
79516  * through main algorithm.
79517  */
79518  x->n = 0;
79519  return;
79520  }
79521 
79522  DUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * nx));
79523  x->n = nx;
79524 
79525  nz = z->n;
79526  for (i = 0; i < y->n; i++) {
79527 #if defined(DUK_USE_64BIT_OPS)
79528  duk_uint64_t tmp = 0U;
79529  for (j = 0; j < nz; j++) {
79530  tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
79531  x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
79532  tmp = tmp >> 32;
79533  }
79534  if (tmp > 0) {
79535  DUK_ASSERT(i + j < nx);
79536  DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
79537  DUK_ASSERT(x->v[i+j] == 0U);
79538  x->v[i+j] = (duk_uint32_t) tmp;
79539  }
79540 #else
79541  /*
79542  * Multiply + add + carry for 32-bit components using only 16x16->32
79543  * multiplies and carry detection based on unsigned overflow.
79544  *
79545  * 1st mult, 32-bit: (A*2^16 + B)
79546  * 2nd mult, 32-bit: (C*2^16 + D)
79547  * 3rd add, 32-bit: E
79548  * 4th add, 32-bit: F
79549  *
79550  * (AC*2^16 + B) * (C*2^16 + D) + E + F
79551  * = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
79552  * = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
79553  * = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
79554  */
79555  duk_uint32_t a, b, c, d, e, f;
79556  duk_uint32_t r, s, t;
79557 
79558  a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
79559 
79560  f = 0;
79561  for (j = 0; j < nz; j++) {
79562  c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
79563  e = x->v[i+j];
79564 
79565  /* build result as: (r << 32) + s: start with (BD + E + F) */
79566  r = 0;
79567  s = b * d;
79568 
79569  /* add E */
79570  t = s + e;
79571  if (t < s) { r++; } /* carry */
79572  s = t;
79573 
79574  /* add F */
79575  t = s + f;
79576  if (t < s) { r++; } /* carry */
79577  s = t;
79578 
79579  /* add BC*2^16 */
79580  t = b * c;
79581  r += (t >> 16);
79582  t = s + ((t & 0xffffUL) << 16);
79583  if (t < s) { r++; } /* carry */
79584  s = t;
79585 
79586  /* add AD*2^16 */
79587  t = a * d;
79588  r += (t >> 16);
79589  t = s + ((t & 0xffffUL) << 16);
79590  if (t < s) { r++; } /* carry */
79591  s = t;
79592 
79593  /* add AC*2^32 */
79594  t = a * c;
79595  r += t;
79596 
79597  DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
79598  (unsigned long) y->v[i], (unsigned long) z->v[j],
79599  (unsigned long) x->v[i+j], (unsigned long) r,
79600  (unsigned long) s));
79601 
79602  x->v[i+j] = s;
79603  f = r;
79604  }
79605  if (f > 0U) {
79606  DUK_ASSERT(i + j < nx);
79607  DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
79608  DUK_ASSERT(x->v[i+j] == 0U);
79609  x->v[i+j] = (duk_uint32_t) f;
79610  }
79611 #endif /* DUK_USE_64BIT_OPS */
79612  }
79613 
79614  duk__bi_normalize(x);
79615  DUK_ASSERT(duk__bi_is_valid(x));
79616 }
79617 
79618 /* x <- y * z */
79619 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
79620  duk__bigint tmp;
79621 
79622  DUK_ASSERT(duk__bi_is_valid(y));
79623 
79624  /* XXX: this could be optimized */
79625  duk__bi_set_small(&tmp, z);
79626  duk__bi_mul(x, y, &tmp);
79627 
79628  DUK_ASSERT(duk__bi_is_valid(x));
79629 }
79630 
79631 /* x <- x * y, use t as temp */
79632 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
79633  duk__bi_mul(t, x, y);
79634  duk__bi_copy(x, t);
79635 }
79636 
79637 /* x <- x * y, use t as temp */
79638 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
79639  duk__bi_mul_small(t, x, y);
79640  duk__bi_copy(x, t);
79641 }
79642 
79643 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
79644  DUK_ASSERT(duk__bi_is_valid(x));
79645  return (x->n == 0) || ((x->v[0] & 0x01) == 0);
79646 }
79647 
79648 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
79649  DUK_ASSERT(duk__bi_is_valid(x));
79650  return (x->n == 0); /* this is the case for normalized numbers */
79651 }
79652 
79653 /* Bigint is 2^52. Used to detect normalized IEEE double mantissa values
79654  * which are at the lowest edge (next floating point value downwards has
79655  * a different exponent). The lowest mantissa has the form:
79656  *
79657  * 1000........000 (52 zeroes; only "hidden bit" is set)
79658  */
79659 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
79660  DUK_ASSERT(duk__bi_is_valid(x));
79661  return (duk_small_int_t)
79662  (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
79663 }
79664 
79665 /* x <- (1<<y) */
79666 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
79667  duk_small_int_t n, r;
79668 
79669  n = (y / 32) + 1;
79670  DUK_ASSERT(n > 0);
79671  r = y % 32;
79672  DUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * n);
79673  x->n = n;
79674  x->v[n - 1] = (((duk_uint32_t) 1) << r);
79675 }
79676 
79677 /* x <- b^y; use t1 and t2 as temps */
79678 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) {
79679  /* Fast path the binary case */
79680 
79681  DUK_ASSERT(x != t1 && x != t2 && t1 != t2); /* distinct bignums, easy mistake to make */
79682  DUK_ASSERT(b >= 0);
79683  DUK_ASSERT(y >= 0);
79684 
79685  if (b == 2) {
79686  duk__bi_twoexp(x, y);
79687  return;
79688  }
79689 
79690  /* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
79691 
79692  DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
79693 
79694  duk__bi_set_small(x, 1);
79695  duk__bi_set_small(t1, b);
79696  for (;;) {
79697  /* Loop structure ensures that we don't compute t1^2 unnecessarily
79698  * on the final round, as that might create a bignum exceeding the
79699  * current DUK__BI_MAX_PARTS limit.
79700  */
79701  if (y & 0x01) {
79702  duk__bi_mul_copy(x, t1, t2);
79703  }
79704  y = y >> 1;
79705  if (y == 0) {
79706  break;
79707  }
79708  duk__bi_mul_copy(t1, t1, t2);
79709  }
79710 
79711  DUK__BI_PRINT("exp_small result", x);
79712 }
79713 
79714 /*
79715  * A Dragon4 number-to-string variant, based on:
79716  *
79717  * Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
79718  * Accurately"
79719  *
79720  * Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
79721  * Quickly and Accurately"
79722  *
79723  * The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
79724  * i.e. the base implementation without logarithm estimation speedups
79725  * (these would increase code footprint considerably). Fixed-format output
79726  * does not follow the suggestions in the paper; instead, we generate an
79727  * extra digit and round-with-carry.
79728  *
79729  * The same algorithm is used for number parsing (with b=10 and B=2)
79730  * by generating one extra digit and doing rounding manually.
79731  *
79732  * See doc/number-conversion.rst for limitations.
79733  */
79734 
79735 /* Maximum number of digits generated. */
79736 #define DUK__MAX_OUTPUT_DIGITS 1040 /* (Number.MAX_VALUE).toString(2).length == 1024, + spare */
79737 
79738 /* Maximum number of characters in formatted value. */
79739 #define DUK__MAX_FORMATTED_LENGTH 1040 /* (-Number.MAX_VALUE).toString(2).length == 1025, + spare */
79740 
79741 /* Number and (minimum) size of bigints in the nc_ctx structure. */
79742 #define DUK__NUMCONV_CTX_NUM_BIGINTS 7
79743 #define DUK__NUMCONV_CTX_BIGINTS_SIZE (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
79744 
79745 typedef struct {
79746  /* Currently about 7*152 = 1064 bytes. The space for these
79747  * duk__bigints is used also as a temporary buffer for generating
79748  * the final string. This is a bit awkard; a union would be
79749  * more correct.
79750  */
79751  duk__bigint f, r, s, mp, mm, t1, t2;
79752 
79753  duk_small_int_t is_s2n; /* if 1, doing a string-to-number; else doing a number-to-string */
79754  duk_small_int_t is_fixed; /* if 1, doing a fixed format output (not free format) */
79755  duk_small_int_t req_digits; /* requested number of output digits; 0 = free-format */
79756  duk_small_int_t abs_pos; /* digit position is absolute, not relative */
79757  duk_small_int_t e; /* exponent for 'f' */
79758  duk_small_int_t b; /* input radix */
79759  duk_small_int_t B; /* output radix */
79760  duk_small_int_t k; /* see algorithm */
79761  duk_small_int_t low_ok; /* see algorithm */
79762  duk_small_int_t high_ok; /* see algorithm */
79763  duk_small_int_t unequal_gaps; /* m+ != m- (very rarely) */
79764 
79765  /* Buffer used for generated digits, values are in the range [0,B-1]. */
79766  duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
79767  duk_small_int_t count; /* digit count */
79769 
79770 /* Note: computes with 'idx' in assertions, so caller beware.
79771  * 'idx' is preincremented, i.e. '1' on first call, because it
79772  * is more convenient for the caller.
79773  */
79774 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x) do { \
79775  DUK_ASSERT((preinc_idx) - 1 >= 0); \
79776  DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
79777  ((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
79778  } while (0)
79779 
79780 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
79781  duk_uint8_t *p;
79782  duk_size_t len;
79783  duk_small_int_t dig;
79784  duk_small_int_t t;
79785 
79786  DUK_ASSERT(radix >= 2 && radix <= 36);
79787 
79788  /* A 32-bit unsigned integer formats to at most 32 digits (the
79789  * worst case happens with radix == 2). Output the digits backwards,
79790  * and use a memmove() to get them in the right place.
79791  */
79792 
79793  p = buf + 32;
79794  for (;;) {
79795  t = x / radix;
79796  dig = x - t * radix;
79797  x = t;
79798 
79799  DUK_ASSERT(dig >= 0 && dig < 36);
79800  *(--p) = DUK__DIGITCHAR(dig);
79801 
79802  if (x == 0) {
79803  break;
79804  }
79805  }
79806  len = (duk_size_t) ((buf + 32) - p);
79807 
79808  DUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);
79809 
79810  return len;
79811 }
79812 
79813 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
79814  duk_small_int_t lowest_mantissa;
79815 
79816 #if 1
79817  /* Assume IEEE round-to-even, so that shorter encoding can be used
79818  * when round-to-even would produce correct result. By removing
79819  * this check (and having low_ok == high_ok == 0) the results would
79820  * still be accurate but in some cases longer than necessary.
79821  */
79822  if (duk__bi_is_even(&nc_ctx->f)) {
79823  DUK_DDD(DUK_DDDPRINT("f is even"));
79824  nc_ctx->low_ok = 1;
79825  nc_ctx->high_ok = 1;
79826  } else {
79827  DUK_DDD(DUK_DDDPRINT("f is odd"));
79828  nc_ctx->low_ok = 0;
79829  nc_ctx->high_ok = 0;
79830  }
79831 #else
79832  /* Note: not honoring round-to-even should work but now generates incorrect
79833  * results. For instance, 1e23 serializes to "a000...", i.e. the first digit
79834  * equals the radix (10). Scaling stops one step too early in this case.
79835  * Don't know why this is the case, but since this code path is unused, it
79836  * doesn't matter.
79837  */
79838  nc_ctx->low_ok = 0;
79839  nc_ctx->high_ok = 0;
79840 #endif
79841 
79842  /* For string-to-number, pretend we never have the lowest mantissa as there
79843  * is no natural "precision" for inputs. Having lowest_mantissa == 0, we'll
79844  * fall into the base cases for both e >= 0 and e < 0.
79845  */
79846  if (nc_ctx->is_s2n) {
79847  lowest_mantissa = 0;
79848  } else {
79849  lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
79850  }
79851 
79852  nc_ctx->unequal_gaps = 0;
79853  if (nc_ctx->e >= 0) {
79854  /* exponent non-negative (and thus not minimum exponent) */
79855 
79856  if (lowest_mantissa) {
79857  /* (>= e 0) AND (= f (expt b (- p 1)))
79858  *
79859  * be <- (expt b e) == b^e
79860  * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
79861  * r <- (* f be1 2) == 2 * f * b^(e+1) [if b==2 -> f * b^(e+2)]
79862  * s <- (* b 2) [if b==2 -> 4]
79863  * m+ <- be1 == b^(e+1)
79864  * m- <- be == b^e
79865  * k <- 0
79866  * B <- B
79867  * low_ok <- round
79868  * high_ok <- round
79869  */
79870 
79871  DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
79872  "lowest mantissa value for this exponent -> "
79873  "unequal gaps"));
79874 
79875  duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
79876  duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, nc_ctx->b); /* mp <- b^(e+1) */
79877  duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
79878  duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^(e+1) */
79879  duk__bi_set_small(&nc_ctx->s, nc_ctx->b * 2); /* s <- 2 * b */
79880  nc_ctx->unequal_gaps = 1;
79881  } else {
79882  /* (>= e 0) AND (not (= f (expt b (- p 1))))
79883  *
79884  * be <- (expt b e) == b^e
79885  * r <- (* f be 2) == 2 * f * b^e [if b==2 -> f * b^(e+1)]
79886  * s <- 2
79887  * m+ <- be == b^e
79888  * m- <- be == b^e
79889  * k <- 0
79890  * B <- B
79891  * low_ok <- round
79892  * high_ok <- round
79893  */
79894 
79895  DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
79896  "not lowest mantissa for this exponent -> "
79897  "equal gaps"));
79898 
79899  duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2); /* mm <- b^e */
79900  duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm); /* mp <- b^e */
79901  duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
79902  duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp); /* r <- (2 * f) * b^e */
79903  duk__bi_set_small(&nc_ctx->s, 2); /* s <- 2 */
79904  }
79905  } else {
79906  /* When doing string-to-number, lowest_mantissa is always 0 so
79907  * the exponent check, while incorrect, won't matter.
79908  */
79909  if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
79910  lowest_mantissa /* lowest mantissa for this exponent*/) {
79911  /* r <- (* f b 2) [if b==2 -> (* f 4)]
79912  * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2 [if b==2 -> b^(2-e)]
79913  * m+ <- b == 2
79914  * m- <- 1
79915  * k <- 0
79916  * B <- B
79917  * low_ok <- round
79918  * high_ok <- round
79919  */
79920 
79921  DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
79922  "lowest mantissa for this exponent -> "
79923  "unequal gaps"));
79924 
79925  duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, nc_ctx->b * 2); /* r <- (2 * b) * f */
79926  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 */
79927  duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(1-e) * 2 */
79928  duk__bi_set_small(&nc_ctx->mp, 2);
79929  duk__bi_set_small(&nc_ctx->mm, 1);
79930  nc_ctx->unequal_gaps = 1;
79931  } else {
79932  /* r <- (* f 2)
79933  * s <- (* (expt b (- e)) 2) == b^(-e) * 2 [if b==2 -> b^(1-e)]
79934  * m+ <- 1
79935  * m- <- 1
79936  * k <- 0
79937  * B <- B
79938  * low_ok <- round
79939  * high_ok <- round
79940  */
79941 
79942  DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
79943  "lowest mantissa for this exponent -> "
79944  "equal gaps"));
79945 
79946  duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2); /* r <- 2 * f */
79947  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 */
79948  duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2); /* s <- b^(-e) * 2 */
79949  duk__bi_set_small(&nc_ctx->mp, 1);
79950  duk__bi_set_small(&nc_ctx->mm, 1);
79951  }
79952  }
79953 }
79954 
79955 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
79956  duk_small_int_t k = 0;
79957 
79958  /* This is essentially the 'scale' algorithm, with recursion removed.
79959  * Note that 'k' is either correct immediately, or will move in one
79960  * direction in the loop. There's no need to do the low/high checks
79961  * on every round (like the Scheme algorithm does).
79962  *
79963  * The scheme algorithm finds 'k' and updates 's' simultaneously,
79964  * while the logical algorithm finds 'k' with 's' having its initial
79965  * value, after which 's' is updated separately (see the Burger-Dybvig
79966  * paper, Section 3.1, steps 2 and 3).
79967  *
79968  * The case where m+ == m- (almost always) is optimized for, because
79969  * it reduces the bigint operations considerably and almost always
79970  * applies. The scale loop only needs to work with m+, so this works.
79971  */
79972 
79973  /* XXX: this algorithm could be optimized quite a lot by using e.g.
79974  * a logarithm based estimator for 'k' and performing B^n multiplication
79975  * using a lookup table or using some bit-representation based exp
79976  * algorithm. Currently we just loop, with significant performance
79977  * impact for very large and very small numbers.
79978  */
79979 
79980  DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
79981  (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
79982  DUK__BI_PRINT("r(init)", &nc_ctx->r);
79983  DUK__BI_PRINT("s(init)", &nc_ctx->s);
79984  DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
79985  DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
79986 
79987  for (;;) {
79988  DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
79989  DUK__BI_PRINT("r", &nc_ctx->r);
79990  DUK__BI_PRINT("s", &nc_ctx->s);
79991  DUK__BI_PRINT("m+", &nc_ctx->mp);
79992  DUK__BI_PRINT("m-", &nc_ctx->mm);
79993 
79994  duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
79995  if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
79996  DUK_DDD(DUK_DDDPRINT("k is too low"));
79997  /* r <- r
79998  * s <- (* s B)
79999  * m+ <- m+
80000  * m- <- m-
80001  * k <- (+ k 1)
80002  */
80003 
80004  duk__bi_mul_small_copy(&nc_ctx->s, nc_ctx->B, &nc_ctx->t1);
80005  k++;
80006  } else {
80007  break;
80008  }
80009  }
80010 
80011  /* k > 0 -> k was too low, and cannot be too high */
80012  if (k > 0) {
80013  goto skip_dec_k;
80014  }
80015 
80016  for (;;) {
80017  DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
80018  DUK__BI_PRINT("r", &nc_ctx->r);
80019  DUK__BI_PRINT("s", &nc_ctx->s);
80020  DUK__BI_PRINT("m+", &nc_ctx->mp);
80021  DUK__BI_PRINT("m-", &nc_ctx->mm);
80022 
80023  duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 = (+ r m+) */
80024  duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, nc_ctx->B); /* t2 = (* (+ r m+) B) */
80025  if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
80026  DUK_DDD(DUK_DDDPRINT("k is too high"));
80027  /* r <- (* r B)
80028  * s <- s
80029  * m+ <- (* m+ B)
80030  * m- <- (* m- B)
80031  * k <- (- k 1)
80032  */
80033  duk__bi_mul_small_copy(&nc_ctx->r, nc_ctx->B, &nc_ctx->t1);
80034  duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t1);
80035  if (nc_ctx->unequal_gaps) {
80036  DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
80037  duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t1);
80038  }
80039  k--;
80040  } else {
80041  break;
80042  }
80043  }
80044 
80045  skip_dec_k:
80046 
80047  if (!nc_ctx->unequal_gaps) {
80048  DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
80049  duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp); /* mm <- mp */
80050  }
80051  nc_ctx->k = k;
80052 
80053  DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
80054  DUK__BI_PRINT("r(final)", &nc_ctx->r);
80055  DUK__BI_PRINT("s(final)", &nc_ctx->s);
80056  DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
80057  DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
80058 }
80059 
80060 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
80061  duk_small_int_t tc1, tc2; /* terminating conditions */
80062  duk_small_int_t d; /* current digit */
80063  duk_small_int_t count = 0; /* digit count */
80064 
80065  /*
80066  * Digit generation loop.
80067  *
80068  * Different termination conditions:
80069  *
80070  * 1. Free format output. Terminate when shortest accurate
80071  * representation found.
80072  *
80073  * 2. Fixed format output, with specific number of digits.
80074  * Ignore termination conditions, terminate when digits
80075  * generated. Caller requests an extra digit and rounds.
80076  *
80077  * 3. Fixed format output, with a specific absolute cut-off
80078  * position (e.g. 10 digits after decimal point). Note
80079  * that we always generate at least one digit, even if
80080  * the digit is below the cut-off point already.
80081  */
80082 
80083  for (;;) {
80084  DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
80085  (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
80086  (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
80087  DUK__BI_PRINT("r", &nc_ctx->r);
80088  DUK__BI_PRINT("s", &nc_ctx->s);
80089  DUK__BI_PRINT("m+", &nc_ctx->mp);
80090  DUK__BI_PRINT("m-", &nc_ctx->mm);
80091 
80092  /* (quotient-remainder (* r B) s) using a dummy subtraction loop */
80093  duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, nc_ctx->B); /* t1 <- (* r B) */
80094  d = 0;
80095  for (;;) {
80096  if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
80097  break;
80098  }
80099  duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2); /* t1 <- t1 - s */
80100  d++;
80101  }
80102  duk__bi_copy(&nc_ctx->r, &nc_ctx->t1); /* r <- (remainder (* r B) s) */
80103  /* d <- (quotient (* r B) s) (in range 0...B-1) */
80104  DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
80105  DUK__BI_PRINT("r(rem)", &nc_ctx->r);
80106 
80107  duk__bi_mul_small_copy(&nc_ctx->mp, nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
80108  duk__bi_mul_small_copy(&nc_ctx->mm, nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
80109  DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
80110  DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
80111 
80112  /* Terminating conditions. For fixed width output, we just ignore the
80113  * terminating conditions (and pretend that tc1 == tc2 == false). The
80114  * the current shortcut for fixed-format output is to generate a few
80115  * extra digits and use rounding (with carry) to finish the output.
80116  */
80117 
80118  if (nc_ctx->is_fixed == 0) {
80119  /* free-form */
80120  tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
80121 
80122  duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp); /* t1 <- (+ r m+) */
80123  tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
80124 
80125  DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
80126  } else {
80127  /* fixed-format */
80128  tc1 = 0;
80129  tc2 = 0;
80130  }
80131 
80132  /* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
80133  * on purpose, which is taken into account by the macro.
80134  */
80135  count++;
80136 
80137  if (tc1) {
80138  if (tc2) {
80139  /* tc1 = true, tc2 = true */
80140  duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
80141  if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) { /* (< (* r 2) s) */
80142  DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
80143  (long) d, (long) nc_ctx->k));
80144  DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
80145  } else {
80146  DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
80147  (long) (d + 1), (long) nc_ctx->k));
80148  DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
80149  }
80150  break;
80151  } else {
80152  /* tc1 = true, tc2 = false */
80153  DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
80154  (long) d, (long) nc_ctx->k));
80155  DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
80156  break;
80157  }
80158  } else {
80159  if (tc2) {
80160  /* tc1 = false, tc2 = true */
80161  DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
80162  (long) (d + 1), (long) nc_ctx->k));
80163  DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
80164  break;
80165  } else {
80166  /* tc1 = false, tc2 = false */
80167  DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
80168  (long) d, (long) nc_ctx->k));
80169  DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
80170 
80171  /* r <- r (updated above: r <- (remainder (* r B) s)
80172  * s <- s
80173  * m+ <- m+ (updated above: m+ <- (* m+ B)
80174  * m- <- m- (updated above: m- <- (* m- B)
80175  * B, low_ok, high_ok are fixed
80176  */
80177 
80178  /* fall through and continue for-loop */
80179  }
80180  }
80181 
80182  /* fixed-format termination conditions */
80183  if (nc_ctx->is_fixed) {
80184  if (nc_ctx->abs_pos) {
80185  int pos = nc_ctx->k - count + 1; /* count is already incremented, take into account */
80186  DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
80187  (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
80188  if (pos <= nc_ctx->req_digits) {
80189  DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
80190  break;
80191  }
80192  } else {
80193  DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
80194  (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
80195  if (count >= nc_ctx->req_digits) {
80196  DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
80197  break;
80198  }
80199  }
80200  }
80201  } /* for */
80202 
80203  nc_ctx->count = count;
80204 
80205  DUK_DDD(DUK_DDDPRINT("generate finished"));
80206 
80207 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
80208  {
80209  duk_uint8_t buf[2048];
80210  duk_small_int_t i, t;
80211  DUK_MEMZERO(buf, sizeof(buf));
80212  for (i = 0; i < nc_ctx->count; i++) {
80213  t = nc_ctx->digits[i];
80214  if (t < 0 || t > 36) {
80215  buf[i] = (duk_uint8_t) '?';
80216  } else {
80217  buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
80218  }
80219  }
80220  DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
80221  (long) nc_ctx->k, (const char *) buf));
80222  }
80223 #endif
80224 }
80225 
80226 /* Round up digits to a given position. If position is out-of-bounds,
80227  * does nothing. If carry propagates over the first digit, a '1' is
80228  * prepended to digits and 'k' will be updated. Return value indicates
80229  * whether carry propagated over the first digit.
80230  *
80231  * Note that nc_ctx->count is NOT updated based on the rounding position
80232  * (it is updated only if carry overflows over the first digit and an
80233  * extra digit is prepended).
80234  */
80235 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
80236  duk_small_int_t t;
80237  duk_uint8_t *p;
80238  duk_uint8_t roundup_limit;
80239  duk_small_int_t ret = 0;
80240 
80241  /*
80242  * round_idx points to the digit which is considered for rounding; the
80243  * digit to its left is the final digit of the rounded value. If round_idx
80244  * is zero, rounding will be performed; the result will either be an empty
80245  * rounded value or if carry happens a '1' digit is generated.
80246  */
80247 
80248  if (round_idx >= nc_ctx->count) {
80249  DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
80250  (long) round_idx, (long) nc_ctx->count));
80251  return 0;
80252  } else if (round_idx < 0) {
80253  DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
80254  (long) round_idx));
80255  return 0;
80256  }
80257 
80258  /*
80259  * Round-up limit.
80260  *
80261  * For even values, divides evenly, e.g. 10 -> roundup_limit=5.
80262  *
80263  * For odd values, rounds up, e.g. 3 -> roundup_limit=2.
80264  * If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
80265  */
80266  roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
80267 
80268  p = &nc_ctx->digits[round_idx];
80269  if (*p >= roundup_limit) {
80270  DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
80271  /* carry */
80272  for (;;) {
80273  *p = 0;
80274  if (p == &nc_ctx->digits[0]) {
80275  DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
80276  DUK_MEMMOVE((void *) (&nc_ctx->digits[1]),
80277  (const void *) (&nc_ctx->digits[0]),
80278  (size_t) (sizeof(char) * nc_ctx->count));
80279  nc_ctx->digits[0] = 1; /* don't increase 'count' */
80280  nc_ctx->k++; /* position of highest digit changed */
80281  nc_ctx->count++; /* number of digits changed */
80282  ret = 1;
80283  break;
80284  }
80285 
80286  DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
80287  (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
80288  p--;
80289  t = *p;
80290  DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
80291  if (++t < nc_ctx->B) {
80292  DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
80293  *p = (duk_uint8_t) t;
80294  break;
80295  }
80296 
80297  DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
80298  }
80299  }
80300 
80301  return ret;
80302 }
80303 
80304 #define DUK__NO_EXP (65536) /* arbitrary marker, outside valid exp range */
80305 
80306 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
80307  duk_context *ctx,
80308  duk_small_int_t radix,
80309  duk_small_int_t digits,
80310  duk_small_uint_t flags,
80311  duk_small_int_t neg) {
80312  duk_small_int_t k;
80313  duk_small_int_t pos, pos_end;
80314  duk_small_int_t expt;
80315  duk_small_int_t dig;
80316  duk_uint8_t *q;
80317  duk_uint8_t *buf;
80318 
80319  /*
80320  * The string conversion here incorporates all the necessary Ecmascript
80321  * semantics without attempting to be generic. nc_ctx->digits contains
80322  * nc_ctx->count digits (>= 1), with the topmost digit's 'position'
80323  * indicated by nc_ctx->k as follows:
80324  *
80325  * digits="123" count=3 k=0 --> 0.123
80326  * digits="123" count=3 k=1 --> 1.23
80327  * digits="123" count=3 k=5 --> 12300
80328  * digits="123" count=3 k=-1 --> 0.0123
80329  *
80330  * Note that the identifier names used for format selection are different
80331  * in Burger-Dybvig paper and Ecmascript specification (quite confusingly
80332  * so, because e.g. 'k' has a totally different meaning in each). See
80333  * documentation for discussion.
80334  *
80335  * Ecmascript doesn't specify any specific behavior for format selection
80336  * (e.g. when to use exponent notation) for non-base-10 numbers.
80337  *
80338  * The bigint space in the context is reused for string output, as there
80339  * is more than enough space for that (>1kB at the moment), and we avoid
80340  * allocating even more stack.
80341  */
80342 
80343  DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
80344  DUK_ASSERT(nc_ctx->count >= 1);
80345 
80346  k = nc_ctx->k;
80347  buf = (duk_uint8_t *) &nc_ctx->f; /* XXX: union would be more correct */
80348  q = buf;
80349 
80350  /* Exponent handling: if exponent format is used, record exponent value and
80351  * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
80352  *
80353  * toFixed() prevents exponent use; otherwise apply a set of criteria to
80354  * match the other API calls (toString(), toPrecision, etc).
80355  */
80356 
80357  expt = DUK__NO_EXP;
80358  if (!nc_ctx->abs_pos /* toFixed() */) {
80359  if ((flags & DUK_N2S_FLAG_FORCE_EXP) || /* exponential notation forced */
80360  ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) && /* fixed precision and zero padding would be required */
80361  (k - digits >= 1)) || /* (e.g. k=3, digits=2 -> "12X") */
80362  ((k > 21 || k <= -6) && (radix == 10))) { /* toString() conditions */
80363  DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
80364  (long) k, (long) (k - 1)));
80365  expt = k - 1; /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
80366  k = 1; /* generate mantissa with a single leading whole number digit */
80367  }
80368  }
80369 
80370  if (neg) {
80371  *q++ = '-';
80372  }
80373 
80374  /* Start position (inclusive) and end position (exclusive) */
80375  pos = (k >= 1 ? k : 1);
80376  if (nc_ctx->is_fixed) {
80377  if (nc_ctx->abs_pos) {
80378  /* toFixed() */
80379  pos_end = -digits;
80380  } else {
80381  pos_end = k - digits;
80382  }
80383  } else {
80384  pos_end = k - nc_ctx->count;
80385  }
80386  if (pos_end > 0) {
80387  pos_end = 0;
80388  }
80389 
80390  DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
80391  "digits=%ld, abs_pos=%ld",
80392  (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
80393  (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
80394 
80395  /* Digit generation */
80396  while (pos > pos_end) {
80397  DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
80398  (long) pos, (long) pos_end));
80399  if (pos == 0) {
80400  *q++ = (duk_uint8_t) '.';
80401  }
80402  if (pos > k) {
80403  *q++ = (duk_uint8_t) '0';
80404  } else if (pos <= k - nc_ctx->count) {
80405  *q++ = (duk_uint8_t) '0';
80406  } else {
80407  dig = nc_ctx->digits[k - pos];
80408  DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
80409  *q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
80410  }
80411 
80412  pos--;
80413  }
80414  DUK_ASSERT(pos <= 1);
80415 
80416  /* Exponent */
80417  if (expt != DUK__NO_EXP) {
80418  /*
80419  * Exponent notation for non-base-10 numbers isn't specified in Ecmascript
80420  * specification, as it never explicitly turns up: non-decimal numbers can
80421  * only be formatted with Number.prototype.toString([radix]) and for that,
80422  * behavior is not explicitly specified.
80423  *
80424  * Logical choices include formatting the exponent as decimal (e.g. binary
80425  * 100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
80426  * The Dragon4 algorithm (in the original paper) prints the exponent value
80427  * in the target radix B. However, for radix values 15 and above, the
80428  * exponent separator 'e' is no longer easily parseable. Consider, for
80429  * instance, the number "1.faecee+1c".
80430  */
80431 
80432  duk_size_t len;
80433  char expt_sign;
80434 
80435  *q++ = 'e';
80436  if (expt >= 0) {
80437  expt_sign = '+';
80438  } else {
80439  expt_sign = '-';
80440  expt = -expt;
80441  }
80442  *q++ = (duk_uint8_t) expt_sign;
80443  len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
80444  q += len;
80445  }
80446 
80447  duk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));
80448 }
80449 
80450 /*
80451  * Conversion helpers
80452  */
80453 
80454 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
80455  duk_double_union u;
80456  duk_uint32_t tmp;
80457  duk_small_int_t expt;
80458 
80459  /*
80460  * seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
80461  * A B C D E F G H
80462  *
80463  * s sign bit
80464  * eee... exponent field
80465  * fff... fraction
80466  *
80467  * ieee value = 1.ffff... * 2^(e - 1023) (normal)
80468  * = 0.ffff... * 2^(-1022) (denormal)
80469  *
80470  * algorithm v = f * b^e
80471  */
80472 
80473  DUK_DBLUNION_SET_DOUBLE(&u, x);
80474 
80475  nc_ctx->f.n = 2;
80476 
80477  tmp = DUK_DBLUNION_GET_LOW32(&u);
80478  nc_ctx->f.v[0] = tmp;
80479  tmp = DUK_DBLUNION_GET_HIGH32(&u);
80480  nc_ctx->f.v[1] = tmp & 0x000fffffUL;
80481  expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
80482 
80483  if (expt == 0) {
80484  /* denormal */
80485  expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
80486  duk__bi_normalize(&nc_ctx->f);
80487  } else {
80488  /* normal: implicit leading 1-bit */
80489  nc_ctx->f.v[1] |= 0x00100000UL;
80490  expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
80491  DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f)); /* true, because v[1] has at least one bit set */
80492  }
80493 
80494  DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
80495 
80496  nc_ctx->e = expt;
80497 }
80498 
80499 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
80500  duk_double_union u;
80501  duk_small_int_t expt;
80502  duk_small_int_t i;
80503  duk_small_int_t bitstart;
80504  duk_small_int_t bitround;
80505  duk_small_int_t bitidx;
80506  duk_small_int_t skip_round;
80507  duk_uint32_t t, v;
80508 
80509  DUK_ASSERT(nc_ctx->count == 53 + 1);
80510 
80511  /* Sometimes this assert is not true right now; it will be true after
80512  * rounding. See: test-bug-numconv-mantissa-assert.js.
80513  */
80514  DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1); /* zero handled by caller */
80515 
80516  /* Should not be required because the code below always sets both high
80517  * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
80518  * (perhaps because the low part is set (seemingly) conditionally in a
80519  * loop), so this is here to avoid the bogus warning.
80520  */
80521  DUK_MEMZERO((void *) &u, sizeof(u));
80522 
80523  /*
80524  * Figure out how generated digits match up with the mantissa,
80525  * and then perform rounding. If mantissa overflows, need to
80526  * recompute the exponent (it is bumped and may overflow to
80527  * infinity).
80528  *
80529  * For normal numbers the leading '1' is hidden and ignored,
80530  * and the last bit is used for rounding:
80531  *
80532  * rounding pt
80533  * <--------52------->|
80534  * 1 x x x x ... x x x x|y ==> x x x x ... x x x x
80535  *
80536  * For denormals, the leading '1' is included in the number,
80537  * and the rounding point is different:
80538  *
80539  * rounding pt
80540  * <--52 or less--->|
80541  * 1 x x x x ... x x|x x y ==> 0 0 ... 1 x x ... x x
80542  *
80543  * The largest denormals will have a mantissa beginning with
80544  * a '1' (the explicit leading bit); smaller denormals will
80545  * have leading zero bits.
80546  *
80547  * If the exponent would become too high, the result becomes
80548  * Infinity. If the exponent is so small that the entire
80549  * mantissa becomes zero, the result becomes zero.
80550  *
80551  * Note: the Dragon4 'k' is off-by-one with respect to the IEEE
80552  * exponent. For instance, k==0 indicates that the leading '1'
80553  * digit is at the first binary fraction position (0.1xxx...);
80554  * the corresponding IEEE exponent would be -1.
80555  */
80556 
80557  skip_round = 0;
80558 
80559  recheck_exp:
80560 
80561  expt = nc_ctx->k - 1; /* IEEE exp without bias */
80562  if (expt > 1023) {
80563  /* Infinity */
80564  bitstart = -255; /* needed for inf: causes mantissa to become zero,
80565  * and rounding to be skipped.
80566  */
80567  expt = 2047;
80568  } else if (expt >= -1022) {
80569  /* normal */
80570  bitstart = 1; /* skip leading digit */
80571  expt += DUK__IEEE_DOUBLE_EXP_BIAS;
80572  DUK_ASSERT(expt >= 1 && expt <= 2046);
80573  } else {
80574  /* denormal or zero */
80575  bitstart = 1023 + expt; /* expt==-1023 -> bitstart=0 (leading 1);
80576  * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
80577  */
80578  expt = 0;
80579  }
80580  bitround = bitstart + 52;
80581 
80582  DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
80583  (long) expt, (long) bitstart, (long) bitround));
80584 
80585  if (!skip_round) {
80586  if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
80587  /* Corner case: see test-numconv-parse-mant-carry.js. We could
80588  * just bump the exponent and update bitstart, but it's more robust
80589  * to recompute (but avoid rounding twice).
80590  */
80591  DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
80592  skip_round = 1;
80593  goto recheck_exp;
80594  }
80595  }
80596 
80597  /*
80598  * Create mantissa
80599  */
80600 
80601  t = 0;
80602  for (i = 0; i < 52; i++) {
80603  bitidx = bitstart + 52 - 1 - i;
80604  if (bitidx >= nc_ctx->count) {
80605  v = 0;
80606  } else if (bitidx < 0) {
80607  v = 0;
80608  } else {
80609  v = nc_ctx->digits[bitidx];
80610  }
80611  DUK_ASSERT(v == 0 || v == 1);
80612  t += v << (i % 32);
80613  if (i == 31) {
80614  /* low 32 bits is complete */
80615  DUK_DBLUNION_SET_LOW32(&u, t);
80616  t = 0;
80617  }
80618  }
80619  /* t has high mantissa */
80620 
80621  DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
80622  (unsigned long) t,
80623  (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
80624 
80625  DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
80626  t += expt << 20;
80627 #if 0 /* caller handles sign change */
80628  if (negative) {
80629  t |= 0x80000000U;
80630  }
80631 #endif
80632  DUK_DBLUNION_SET_HIGH32(&u, t);
80633 
80634  DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
80635  (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
80636  (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
80637 
80638  *x = DUK_DBLUNION_GET_DOUBLE(&u);
80639 }
80640 
80641 /*
80642  * Exposed number-to-string API
80643  *
80644  * Input: [ number ]
80645  * Output: [ string ]
80646  */
80647 
80648 DUK_INTERNAL void duk_numconv_stringify(duk_context *ctx, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
80649  duk_double_t x;
80650  duk_small_int_t c;
80651  duk_small_int_t neg;
80652  duk_uint32_t uval;
80653  duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
80654  duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
80655 
80656  x = (duk_double_t) duk_require_number(ctx, -1);
80657  duk_pop(ctx);
80658 
80659  /*
80660  * Handle special cases (NaN, infinity, zero).
80661  */
80662 
80663  c = (duk_small_int_t) DUK_FPCLASSIFY(x);
80664  if (DUK_SIGNBIT((double) x)) {
80665  x = -x;
80666  neg = 1;
80667  } else {
80668  neg = 0;
80669  }
80670 
80671  /* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
80672  DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
80673 
80674  if (c == DUK_FP_NAN) {
80675  duk_push_hstring_stridx(ctx, DUK_STRIDX_NAN);
80676  return;
80677  } else if (c == DUK_FP_INFINITE) {
80678  if (neg) {
80679  /* -Infinity */
80680  duk_push_hstring_stridx(ctx, DUK_STRIDX_MINUS_INFINITY);
80681  } else {
80682  /* Infinity */
80683  duk_push_hstring_stridx(ctx, DUK_STRIDX_INFINITY);
80684  }
80685  return;
80686  } else if (c == DUK_FP_ZERO) {
80687  /* We can't shortcut zero here if it goes through special formatting
80688  * (such as forced exponential notation).
80689  */
80690  ;
80691  }
80692 
80693  /*
80694  * Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
80695  * specially, as they're very likely for embedded programs. This
80696  * is now done for all radix values. We must be careful not to use
80697  * the fast path when special formatting (e.g. forced exponential)
80698  * is in force.
80699  *
80700  * XXX: could save space by supporting radix 10 only and using
80701  * sprintf "%lu" for the fast path and for exponent formatting.
80702  */
80703 
80704  uval = (unsigned int) x;
80705  if (((double) uval) == x && /* integer number in range */
80706  flags == 0) { /* no special formatting */
80707  /* use bigint area as a temp */
80708  duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
80709  duk_uint8_t *p = buf;
80710 
80711  DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1); /* max size: radix=2 + sign */
80712  if (neg && uval != 0) {
80713  /* no negative sign for zero */
80714  *p++ = (duk_uint8_t) '-';
80715  }
80716  p += duk__dragon4_format_uint32(p, uval, radix);
80717  duk_push_lstring(ctx, (const char *) buf, (duk_size_t) (p - buf));
80718  return;
80719  }
80720 
80721  /*
80722  * Dragon4 setup.
80723  *
80724  * Convert double from IEEE representation for conversion;
80725  * normal finite values have an implicit leading 1-bit. The
80726  * slow path algorithm doesn't handle zero, so zero is special
80727  * cased here but still creates a valid nc_ctx, and goes
80728  * through normal formatting in case special formatting has
80729  * been requested (e.g. forced exponential format: 0 -> "0e+0").
80730  */
80731 
80732  /* Would be nice to bulk clear the allocation, but the context
80733  * is 1-2 kilobytes and nothing should rely on it being zeroed.
80734  */
80735 #if 0
80736  DUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx)); /* slow init, do only for slow path cases */
80737 #endif
80738 
80739  nc_ctx->is_s2n = 0;
80740  nc_ctx->b = 2;
80741  nc_ctx->B = radix;
80742  nc_ctx->abs_pos = 0;
80743  if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
80744  nc_ctx->is_fixed = 1;
80745  if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
80746  /* absolute req_digits; e.g. digits = 1 -> last digit is 0,
80747  * but add an extra digit for rounding.
80748  */
80749  nc_ctx->abs_pos = 1;
80750  nc_ctx->req_digits = (-digits + 1) - 1;
80751  } else {
80752  nc_ctx->req_digits = digits + 1;
80753  }
80754  } else {
80755  nc_ctx->is_fixed = 0;
80756  nc_ctx->req_digits = 0;
80757  }
80758 
80759  if (c == DUK_FP_ZERO) {
80760  /* Zero special case: fake requested number of zero digits; ensure
80761  * no sign bit is printed. Relative and absolute fixed format
80762  * require separate handling.
80763  */
80764  duk_small_int_t count;
80765  if (nc_ctx->is_fixed) {
80766  if (nc_ctx->abs_pos) {
80767  count = digits + 2; /* lead zero + 'digits' fractions + 1 for rounding */
80768  } else {
80769  count = digits + 1; /* + 1 for rounding */
80770  }
80771  } else {
80772  count = 1;
80773  }
80774  DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
80775  DUK_ASSERT(count >= 1);
80776  DUK_MEMZERO((void *) nc_ctx->digits, count);
80777  nc_ctx->count = count;
80778  nc_ctx->k = 1; /* 0.000... */
80779  neg = 0;
80780  goto zero_skip;
80781  }
80782 
80783  duk__dragon4_double_to_ctx(nc_ctx, x); /* -> sets 'f' and 'e' */
80784  DUK__BI_PRINT("f", &nc_ctx->f);
80785  DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
80786 
80787  /*
80788  * Dragon4 slow path digit generation.
80789  */
80790 
80791  duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
80792 
80793  DUK_DDD(DUK_DDDPRINT("after prepare:"));
80794  DUK__BI_PRINT("r", &nc_ctx->r);
80795  DUK__BI_PRINT("s", &nc_ctx->s);
80796  DUK__BI_PRINT("mp", &nc_ctx->mp);
80797  DUK__BI_PRINT("mm", &nc_ctx->mm);
80798 
80799  duk__dragon4_scale(nc_ctx);
80800 
80801  DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
80802  DUK__BI_PRINT("r", &nc_ctx->r);
80803  DUK__BI_PRINT("s", &nc_ctx->s);
80804  DUK__BI_PRINT("mp", &nc_ctx->mp);
80805  DUK__BI_PRINT("mm", &nc_ctx->mm);
80806 
80807  duk__dragon4_generate(nc_ctx);
80808 
80809  /*
80810  * Convert and push final string.
80811  */
80812 
80813  zero_skip:
80814 
80815  if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
80816  /* Perform fixed-format rounding. */
80817  duk_small_int_t roundpos;
80818  if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
80819  /* 'roundpos' is relative to nc_ctx->k and increases to the right
80820  * (opposite of how 'k' changes).
80821  */
80822  roundpos = -digits; /* absolute position for digit considered for rounding */
80823  roundpos = nc_ctx->k - roundpos;
80824  } else {
80825  roundpos = digits;
80826  }
80827  DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
80828  (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
80829  (void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
80830 
80831  /* Note: 'count' is currently not adjusted by rounding (i.e. the
80832  * digits are not "chopped off". That shouldn't matter because
80833  * the digit position (absolute or relative) is passed on to the
80834  * convert-and-push function.
80835  */
80836  }
80837 
80838  duk__dragon4_convert_and_push(nc_ctx, ctx, radix, digits, flags, neg);
80839 }
80840 
80841 /*
80842  * Exposed string-to-number API
80843  *
80844  * Input: [ string ]
80845  * Output: [ number ]
80846  *
80847  * If number parsing fails, a NaN is pushed as the result. If number parsing
80848  * fails due to an internal error, an InternalError is thrown.
80849  */
80850 
80851 DUK_INTERNAL void duk_numconv_parse(duk_context *ctx, duk_small_int_t radix, duk_small_uint_t flags) {
80852  duk_hthread *thr = (duk_hthread *) ctx;
80853  duk__numconv_stringify_ctx nc_ctx_alloc; /* large context; around 2kB now */
80854  duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
80855  duk_double_t res;
80856  duk_hstring *h_str;
80857  duk_small_int_t expt;
80858  duk_small_int_t expt_neg;
80859  duk_small_int_t expt_adj;
80860  duk_small_int_t neg;
80861  duk_small_int_t dig;
80862  duk_small_int_t dig_whole;
80863  duk_small_int_t dig_lzero;
80864  duk_small_int_t dig_frac;
80865  duk_small_int_t dig_expt;
80866  duk_small_int_t dig_prec;
80867  const duk__exp_limits *explim;
80868  const duk_uint8_t *p;
80869  duk_small_int_t ch;
80870 
80871  DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
80872  (duk_tval *) duk_get_tval(ctx, -1),
80873  (long) radix, (unsigned long) flags));
80874 
80875  DUK_ASSERT(radix >= 2 && radix <= 36);
80876  DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
80877 
80878  /*
80879  * Preliminaries: trim, sign, Infinity check
80880  *
80881  * We rely on the interned string having a NUL terminator, which will
80882  * cause a parse failure wherever it is encountered. As a result, we
80883  * don't need separate pointer checks.
80884  *
80885  * There is no special parsing for 'NaN' in the specification although
80886  * 'Infinity' (with an optional sign) is allowed in some contexts.
80887  * Some contexts allow plus/minus sign, while others only allow the
80888  * minus sign (like JSON.parse()).
80889  *
80890  * Automatic hex number detection (leading '0x' or '0X') and octal
80891  * number detection (leading '0' followed by at least one octal digit)
80892  * is done here too.
80893  *
80894  * Symbols are not explicitly rejected here (that's up to the caller).
80895  * If a symbol were passed here, it should ultimately safely fail
80896  * parsing due to a syntax error.
80897  */
80898 
80899  if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
80900  /* Leading / trailing whitespace is sometimes accepted and
80901  * sometimes not. After white space trimming, all valid input
80902  * characters are pure ASCII.
80903  */
80904  duk_trim(ctx, -1);
80905  }
80906  h_str = duk_require_hstring(ctx, -1);
80907  DUK_ASSERT(h_str != NULL);
80908  p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
80909 
80910  neg = 0;
80911  ch = *p;
80912  if (ch == (duk_small_int_t) '+') {
80913  if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
80914  DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
80915  goto parse_fail;
80916  }
80917  p++;
80918  } else if (ch == (duk_small_int_t) '-') {
80919  if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
80920  DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
80921  goto parse_fail;
80922  }
80923  p++;
80924  neg = 1;
80925  }
80926 
80927  if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
80928  /* Don't check for Infinity unless the context allows it.
80929  * 'Infinity' is a valid integer literal in e.g. base-36:
80930  *
80931  * parseInt('Infinity', 36)
80932  * 1461559270678
80933  */
80934 
80935  if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
80936  DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
80937  goto parse_fail;
80938  } else {
80939  res = DUK_DOUBLE_INFINITY;
80940  goto negcheck_and_ret;
80941  }
80942  }
80943  ch = *p;
80944  if (ch == (duk_small_int_t) '0') {
80945  duk_small_int_t detect_radix = 0;
80946  ch = DUK_LOWERCASE_CHAR_ASCII(p[1]); /* 'x' or 'X' -> 'x' */
80947  if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
80948  DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
80949  detect_radix = 16;
80950 #if 0
80951  } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
80952  (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
80953  DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
80954  detect_radix = 8;
80955 
80956  /* NOTE: if this legacy octal case is added back, it has
80957  * different flags and 'p' advance so this needs to be
80958  * reworked.
80959  */
80960  flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO; /* interpret e.g. '09' as '0', not NaN */
80961  p += 1;
80962 #endif
80963  } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
80964  DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
80965  detect_radix = 8;
80966  } else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
80967  DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
80968  detect_radix = 2;
80969  }
80970  if (detect_radix > 0) {
80971  radix = detect_radix;
80972  /* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
80973  flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
80974  DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
80975  DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
80976  flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO; /* allow e.g. '0x0009' and '0b00010001' */
80977  p += 2;
80978  }
80979  }
80980 
80981  /*
80982  * Scan number and setup for Dragon4.
80983  *
80984  * The fast path case is detected during setup: an integer which
80985  * can be converted without rounding, no net exponent. The fast
80986  * path could be implemented as a separate scan, but may not really
80987  * be worth it: the multiplications for building 'f' are not
80988  * expensive when 'f' is small.
80989  *
80990  * The significand ('f') must contain enough bits of (apparent)
80991  * accuracy, so that Dragon4 will generate enough binary output digits.
80992  * For decimal numbers, this means generating a 20-digit significand,
80993  * which should yield enough practical accuracy to parse IEEE doubles.
80994  * In fact, the Ecmascript specification explicitly allows an
80995  * implementation to treat digits beyond 20 as zeroes (and even
80996  * to round the 20th digit upwards). For non-decimal numbers, the
80997  * appropriate number of digits has been precomputed for comparable
80998  * accuracy.
80999  *
81000  * Digit counts:
81001  *
81002  * [ dig_lzero ]
81003  * |
81004  * .+-..---[ dig_prec ]----.
81005  * | || |
81006  * 0000123.456789012345678901234567890e+123456
81007  * | | | | | |
81008  * `--+--' `------[ dig_frac ]-------' `-+--'
81009  * | |
81010  * [ dig_whole ] [ dig_expt ]
81011  *
81012  * dig_frac and dig_expt are -1 if not present
81013  * dig_lzero is only computed for whole number part
81014  *
81015  * Parsing state
81016  *
81017  * Parsing whole part dig_frac < 0 AND dig_expt < 0
81018  * Parsing fraction part dig_frac >= 0 AND dig_expt < 0
81019  * Parsing exponent part dig_expt >= 0 (dig_frac may be < 0 or >= 0)
81020  *
81021  * Note: in case we hit an implementation limit (like exponent range),
81022  * we should throw an error, NOT return NaN or Infinity. Even with
81023  * very large exponent (or significand) values the final result may be
81024  * finite, so NaN/Infinity would be incorrect.
81025  */
81026 
81027  duk__bi_set_small(&nc_ctx->f, 0);
81028  dig_prec = 0;
81029  dig_lzero = 0;
81030  dig_whole = 0;
81031  dig_frac = -1;
81032  dig_expt = -1;
81033  expt = 0;
81034  expt_adj = 0; /* essentially tracks digit position of lowest 'f' digit */
81035  expt_neg = 0;
81036  for (;;) {
81037  ch = *p++;
81038 
81039  DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
81040  "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
81041  (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
81042  (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
81043  (long) dig_expt, (long) dig_lzero, (long) dig_prec));
81044  DUK__BI_PRINT("f", &nc_ctx->f);
81045 
81046  /* Most common cases first. */
81047  if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
81048  dig = (duk_small_int_t) ch - '0' + 0;
81049  } else if (ch == (duk_small_int_t) '.') {
81050  /* A leading digit is not required in some cases, e.g. accept ".123".
81051  * In other cases (JSON.parse()) a leading digit is required. This
81052  * is checked for after the loop.
81053  */
81054  if (dig_frac >= 0 || dig_expt >= 0) {
81055  if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
81056  DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
81057  break;
81058  } else {
81059  DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
81060  goto parse_fail;
81061  }
81062  }
81063 
81064  if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
81065  /* Some contexts don't allow fractions at all; this can't be a
81066  * post-check because the state ('f' and expt) would be incorrect.
81067  */
81068  if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
81069  DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
81070  break;
81071  } else {
81072  DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
81073  }
81074  }
81075 
81076  DUK_DDD(DUK_DDDPRINT("start fraction part"));
81077  dig_frac = 0;
81078  continue;
81079  } else if (ch == (duk_small_int_t) 0) {
81080  DUK_DDD(DUK_DDDPRINT("NUL termination"));
81081  break;
81082  } else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
81083  dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
81084  /* Note: we don't parse back exponent notation for anything else
81085  * than radix 10, so this is not an ambiguous check (e.g. hex
81086  * exponent values may have 'e' either as a significand digit
81087  * or as an exponent separator).
81088  *
81089  * If the exponent separator occurs twice, 'e' will be interpreted
81090  * as a digit (= 14) and will be rejected as an invalid decimal
81091  * digit.
81092  */
81093 
81094  DUK_DDD(DUK_DDDPRINT("start exponent part"));
81095 
81096  /* Exponent without a sign or with a +/- sign is accepted
81097  * by all call sites (even JSON.parse()).
81098  */
81099  ch = *p;
81100  if (ch == (duk_small_int_t) '-') {
81101  expt_neg = 1;
81102  p++;
81103  } else if (ch == (duk_small_int_t) '+') {
81104  p++;
81105  }
81106  dig_expt = 0;
81107  continue;
81108  } else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
81109  dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
81110  } else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
81111  dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
81112  } else {
81113  dig = 255; /* triggers garbage digit check below */
81114  }
81115  DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
81116 
81117  if (dig >= radix) {
81118  if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
81119  DUK_DDD(DUK_DDDPRINT("garbage termination"));
81120  break;
81121  } else {
81122  DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
81123  goto parse_fail;
81124  }
81125  }
81126 
81127  if (dig_expt < 0) {
81128  /* whole or fraction digit */
81129 
81130  if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
81131  /* significant from precision perspective */
81132 
81133  duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
81134  if (f_zero && dig == 0) {
81135  /* Leading zero is not counted towards precision digits; not
81136  * in the integer part, nor in the fraction part.
81137  */
81138  if (dig_frac < 0) {
81139  dig_lzero++;
81140  }
81141  } else {
81142  /* XXX: join these ops (multiply-accumulate), but only if
81143  * code footprint decreases.
81144  */
81145  duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, radix);
81146  duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, dig);
81147  dig_prec++;
81148  }
81149  } else {
81150  /* Ignore digits beyond a radix-specific limit, but note them
81151  * in expt_adj.
81152  */
81153  expt_adj++;
81154  }
81155 
81156  if (dig_frac >= 0) {
81157  dig_frac++;
81158  expt_adj--;
81159  } else {
81160  dig_whole++;
81161  }
81162  } else {
81163  /* exponent digit */
81164 
81165  expt = expt * radix + dig;
81166  if (expt > DUK_S2N_MAX_EXPONENT) {
81167  /* impose a reasonable exponent limit, so that exp
81168  * doesn't need to get tracked using a bigint.
81169  */
81170  DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
81171  goto parse_explimit_error;
81172  }
81173  dig_expt++;
81174  }
81175  }
81176 
81177  /* Leading zero. */
81178 
81179  if (dig_lzero > 0 && dig_whole > 1) {
81180  if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
81181  DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
81182  goto parse_fail;
81183  }
81184  }
81185 
81186  /* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
81187 
81188  if (dig_whole == 0) {
81189  if (dig_frac == 0) {
81190  /* "." is not accepted in any format */
81191  DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
81192  goto parse_fail;
81193  } else if (dig_frac > 0) {
81194  /* ".123" */
81195  if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
81196  DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
81197  "leading integer digit(s)"));
81198  goto parse_fail;
81199  }
81200  } else {
81201  /* empty ("") is allowed in some formats (e.g. Number(''), as zero */
81202  if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
81203  DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
81204  goto parse_fail;
81205  }
81206  }
81207  } else {
81208  if (dig_frac == 0) {
81209  /* "123." is allowed in some formats */
81210  if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
81211  DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
81212  goto parse_fail;
81213  }
81214  } else if (dig_frac > 0) {
81215  /* "123.456" */
81216  ;
81217  } else {
81218  /* "123" */
81219  ;
81220  }
81221  }
81222 
81223  /* Exponent without digits (e.g. "1e" or "1e+"). If trailing garbage is
81224  * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
81225  */
81226 
81227  if (dig_expt == 0) {
81228  if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
81229  DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
81230  goto parse_fail;
81231  }
81232  DUK_ASSERT(expt == 0);
81233  }
81234 
81235  if (expt_neg) {
81236  expt = -expt;
81237  }
81238  DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
81239  (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
81240  expt += expt_adj;
81241 
81242  /* Fast path check. */
81243 
81244  if (nc_ctx->f.n <= 1 && /* 32-bit value */
81245  expt == 0 /* no net exponent */) {
81246  /* Fast path is triggered for no exponent and also for balanced exponent
81247  * and fraction parts, e.g. for "1.23e2" == "123". Remember to respect
81248  * zero sign.
81249  */
81250 
81251  /* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
81252  DUK_DDD(DUK_DDDPRINT("fast path number parse"));
81253  if (nc_ctx->f.n == 1) {
81254  res = (double) nc_ctx->f.v[0];
81255  } else {
81256  res = 0.0;
81257  }
81258  goto negcheck_and_ret;
81259  }
81260 
81261  /* Significand ('f') padding. */
81262 
81263  while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
81264  /* Pad significand with "virtual" zero digits so that Dragon4 will
81265  * have enough (apparent) precision to work with.
81266  */
81267  DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
81268  duk__bi_mul_small_copy(&nc_ctx->f, radix, &nc_ctx->t1);
81269  DUK__BI_PRINT("f", &nc_ctx->f);
81270  expt--;
81271  dig_prec++;
81272  }
81273 
81274  DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
81275 
81276  /* Detect zero special case. */
81277 
81278  if (nc_ctx->f.n == 0) {
81279  /* This may happen even after the fast path check, if exponent is
81280  * not balanced (e.g. "0e1"). Remember to respect zero sign.
81281  */
81282  DUK_DDD(DUK_DDDPRINT("significand is zero"));
81283  res = 0.0;
81284  goto negcheck_and_ret;
81285  }
81286 
81287 
81288  /* Quick reject of too large or too small exponents. This check
81289  * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
81290  * so zero check must be above.
81291  */
81292 
81293  explim = &duk__str2num_exp_limits[radix - 2];
81294  if (expt > explim->upper) {
81295  DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
81296  res = (duk_double_t) DUK_DOUBLE_INFINITY;
81297  goto negcheck_and_ret;
81298  } else if (expt < explim->lower) {
81299  DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
81300  res = (duk_double_t) 0.0;
81301  goto negcheck_and_ret;
81302  }
81303 
81304  nc_ctx->is_s2n = 1;
81305  nc_ctx->e = expt;
81306  nc_ctx->b = radix;
81307  nc_ctx->B = 2;
81308  nc_ctx->is_fixed = 1;
81309  nc_ctx->abs_pos = 0;
81310  nc_ctx->req_digits = 53 + 1;
81311 
81312  DUK__BI_PRINT("f", &nc_ctx->f);
81313  DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
81314 
81315  /*
81316  * Dragon4 slow path (binary) digit generation.
81317  * An extra digit is generated for rounding.
81318  */
81319 
81320  duk__dragon4_prepare(nc_ctx); /* setup many variables in nc_ctx */
81321 
81322  DUK_DDD(DUK_DDDPRINT("after prepare:"));
81323  DUK__BI_PRINT("r", &nc_ctx->r);
81324  DUK__BI_PRINT("s", &nc_ctx->s);
81325  DUK__BI_PRINT("mp", &nc_ctx->mp);
81326  DUK__BI_PRINT("mm", &nc_ctx->mm);
81327 
81328  duk__dragon4_scale(nc_ctx);
81329 
81330  DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
81331  DUK__BI_PRINT("r", &nc_ctx->r);
81332  DUK__BI_PRINT("s", &nc_ctx->s);
81333  DUK__BI_PRINT("mp", &nc_ctx->mp);
81334  DUK__BI_PRINT("mm", &nc_ctx->mm);
81335 
81336  duk__dragon4_generate(nc_ctx);
81337 
81338  DUK_ASSERT(nc_ctx->count == 53 + 1);
81339 
81340  /*
81341  * Convert binary digits into an IEEE double. Need to handle
81342  * denormals and rounding correctly.
81343  *
81344  * Some call sites currently assume the result is always a
81345  * non-fastint double. If this is changed, check all call
81346  * sites.
81347  */
81348 
81349  duk__dragon4_ctx_to_double(nc_ctx, &res);
81350  goto negcheck_and_ret;
81351 
81352  negcheck_and_ret:
81353  if (neg) {
81354  res = -res;
81355  }
81356  duk_pop(ctx);
81357  duk_push_number(ctx, (double) res);
81358  DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(ctx, -1)));
81359  return;
81360 
81361  parse_fail:
81362  DUK_DDD(DUK_DDDPRINT("parse failed"));
81363  duk_pop(ctx);
81364  duk_push_nan(ctx);
81365  return;
81366 
81367  parse_explimit_error:
81368  DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
81369  DUK_ERROR_RANGE(thr, "exponent too large");
81370  return;
81371 }
81372 
81373 /* automatic undefs */
81374 #undef DUK__BI_MAX_PARTS
81375 #undef DUK__BI_PRINT
81376 #undef DUK__DIGITCHAR
81377 #undef DUK__DRAGON4_OUTPUT_PREINC
81378 #undef DUK__IEEE_DOUBLE_EXP_BIAS
81379 #undef DUK__IEEE_DOUBLE_EXP_MIN
81380 #undef DUK__MAX_FORMATTED_LENGTH
81381 #undef DUK__MAX_OUTPUT_DIGITS
81382 #undef DUK__NO_EXP
81383 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
81384 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
81385 /*
81386  * Regexp compilation.
81387  *
81388  * See doc/regexp.rst for a discussion of the compilation approach and
81389  * current limitations.
81390  *
81391  * Regexp bytecode assumes jumps can be expressed with signed 32-bit
81392  * integers. Consequently the bytecode size must not exceed 0x7fffffffL.
81393  * The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
81394  * in many places. Although this could be changed, the bytecode format
81395  * limit would still prevent regexps exceeding the signed 32-bit limit
81396  * from working.
81397  *
81398  * XXX: The implementation does not prevent bytecode from exceeding the
81399  * maximum supported size. This could be done by limiting the maximum
81400  * input string size (assuming an upper bound can be computed for number
81401  * of bytecode bytes emitted per input byte) or checking buffer maximum
81402  * size when emitting bytecode (slower).
81403  */
81404 
81405 /* #include duk_internal.h -> already included */
81406 
81407 #if defined(DUK_USE_REGEXP_SUPPORT)
81408 
81409 /*
81410  * Helper macros
81411  */
81412 
81413 #define DUK__RE_INITIAL_BUFSIZE 64
81414 
81415 #define DUK__RE_BUFLEN(re_ctx) \
81416  DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
81417 
81418 /*
81419  * Disjunction struct: result of parsing a disjunction
81420  */
81421 
81422 typedef struct {
81423  /* Number of characters that the atom matches (e.g. 3 for 'abc'),
81424  * -1 if atom is complex and number of matched characters either
81425  * varies or is not known.
81426  */
81427  duk_int32_t charlen;
81428 
81429 #if 0
81430  /* These are not needed to implement quantifier capture handling,
81431  * but might be needed at some point.
81432  */
81433 
81434  /* re_ctx->captures at start and end of atom parsing.
81435  * Since 'captures' indicates highest capture number emitted
81436  * so far in a DUK_REOP_SAVE, the captures numbers saved by
81437  * the atom are: ]start_captures,end_captures].
81438  */
81439  duk_uint32_t start_captures;
81440  duk_uint32_t end_captures;
81441 #endif
81443 
81444 /*
81445  * Encoding helpers
81446  *
81447  * Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
81448  * even though the buffer operations will use duk_size_t.
81449  */
81450 
81451 /* XXX: the insert helpers should ensure that the bytecode result is not
81452  * larger than expected (or at least assert for it). Many things in the
81453  * bytecode, like skip offsets, won't work correctly if the bytecode is
81454  * larger than say 2G.
81455  */
81456 
81457 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
81458  if (x < 0) {
81459  return ((duk_uint32_t) (-x)) * 2 + 1;
81460  } else {
81461  return ((duk_uint32_t) x) * 2;
81462  }
81463 }
81464 
81465 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
81466  * maximum size.
81467  */
81468 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
81469  duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
81470  duk_small_int_t len;
81471 
81472  len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
81473  DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, len);
81474  return (duk_uint32_t) len;
81475 }
81476 
81477 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
81478  DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
81479 }
81480 
81481 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
81482 #if defined(DUK_USE_PREFER_SIZE)
81483  duk__append_u32(re_ctx, x);
81484 #else
81485  DUK_ASSERT(x <= 0x7fU);
81486  DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
81487 #endif
81488 }
81489 
81490 #if 0
81491 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
81492  DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
81493 }
81494 #endif
81495 
81496 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
81497  return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
81498 }
81499 
81500 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
81501  DUK_ASSERT(reop <= 0x7fU);
81502  (void) duk__append_7bit(re_ctx, reop);
81503 }
81504 
81505 #if 0 /* unused */
81506 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
81507  duk__append_u32(re_ctx, duk__encode_i32(x));
81508 }
81509 #endif
81510 
81511 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
81512 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
81513  /* Call sites don't need the result length so it's not accumulated. */
81514  while (count-- > 0) {
81515  duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
81516  }
81517 }
81518 
81519 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) {
81520  DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
81521 }
81522 
81523 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
81524  DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
81525 }
81526 
81527 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
81528  DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
81529 }
81530 
81531 /*
81532  * Insert a jump offset at 'offset' to complete an instruction
81533  * (the jump offset is always the last component of an instruction).
81534  * The 'skip' argument must be computed relative to 'offset',
81535  * -without- taking into account the skip field being inserted.
81536  *
81537  * ... A B C ins X Y Z ... (ins may be a JUMP, SPLIT1/SPLIT2, etc)
81538  * => ... A B C ins SKIP X Y Z
81539  *
81540  * Computing the final (adjusted) skip value, which is relative to the
81541  * first byte of the next instruction, is a bit tricky because of the
81542  * variable length UTF-8 encoding. See doc/regexp.rst for discussion.
81543  */
81544 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
81545 #if 0
81546  /* Iterative solution. */
81547  if (skip < 0) {
81548  duk_small_int_t len;
81549  /* two encoding attempts suffices */
81550  len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
81551  len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
81552  DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len); /* no change */
81553  skip -= (duk_int32_t) len;
81554  }
81555 #endif
81556 
81557 #if defined(DUK_USE_PREFER_SIZE)
81558  /* Closed form solution, this produces smallest code.
81559  * See re_neg_jump_offset (closed2).
81560  */
81561  if (skip < 0) {
81562  skip--;
81563  if (skip < -0x3fL) {
81564  skip--;
81565  }
81566  if (skip < -0x3ffL) {
81567  skip--;
81568  }
81569  if (skip < -0x7fffL) {
81570  skip--;
81571  }
81572  if (skip < -0xfffffL) {
81573  skip--;
81574  }
81575  if (skip < -0x1ffffffL) {
81576  skip--;
81577  }
81578  if (skip < -0x3fffffffL) {
81579  skip--;
81580  }
81581  }
81582 #else /* DUK_USE_PREFER_SIZE */
81583  /* Closed form solution, this produces fastest code.
81584  * See re_neg_jump_offset (closed1).
81585  */
81586  if (skip < 0) {
81587  if (skip >= -0x3eL) {
81588  skip -= 1;
81589  } else if (skip >= -0x3fdL) {
81590  skip -= 2;
81591  } else if (skip >= -0x7ffcL) {
81592  skip -= 3;
81593  } else if (skip >= -0xffffbL) {
81594  skip -= 4;
81595  } else if (skip >= -0x1fffffaL) {
81596  skip -= 5;
81597  } else if (skip >= -0x3ffffff9L) {
81598  skip -= 6;
81599  } else {
81600  skip -= 7;
81601  }
81602  }
81603 #endif /* DUK_USE_PREFER_SIZE */
81604 
81605  return duk__insert_i32(re_ctx, offset, skip);
81606 }
81607 
81608 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
81609  return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
81610 }
81611 
81612 /*
81613  * duk_re_range_callback for generating character class ranges.
81614  *
81615  * When ignoreCase is false, the range is simply emitted as is.
81616  * We don't, for instance, eliminate duplicates or overlapping
81617  * ranges in a character class.
81618  *
81619  * When ignoreCase is true, the range needs to be normalized through
81620  * canonicalization. Unfortunately a canonicalized version of a
81621  * continuous range is not necessarily continuous (e.g. [x-{] is
81622  * continuous but [X-{] is not). The current algorithm creates the
81623  * canonicalized range(s) space efficiently at the cost of compile
81624  * time execution time (see doc/regexp.rst for discussion).
81625  *
81626  * Note that the ctx->nranges is a context-wide temporary value
81627  * (this is OK because there cannot be multiple character classes
81628  * being parsed simultaneously).
81629  */
81630 
81631 DUK_LOCAL void duk__generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
81632  duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
81633 
81634  DUK_DD(DUK_DDPRINT("duk__generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
81635  (void *) re_ctx, (long) r1, (long) r2, (long) direct));
81636 
81637  if (!direct && (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE)) {
81638  /*
81639  * Canonicalize a range, generating result ranges as necessary.
81640  * Needs to exhaustively scan the entire range (at most 65536
81641  * code points). If 'direct' is set, caller (lexer) has ensured
81642  * that the range is already canonicalization compatible (this
81643  * is used to avoid unnecessary canonicalization of built-in
81644  * ranges like \W, which are not affected by canonicalization).
81645  *
81646  * NOTE: here is one place where we don't want to support chars
81647  * outside the BMP, because the exhaustive search would be
81648  * massively larger.
81649  */
81650 
81651  duk_codepoint_t i;
81652  duk_codepoint_t t;
81653  duk_codepoint_t r_start, r_end;
81654 
81655  r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
81656  r_end = r_start;
81657  for (i = r1 + 1; i <= r2; i++) {
81658  t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
81659  if (t == r_end + 1) {
81660  r_end = t;
81661  } else {
81662  DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
81663  duk__append_u32(re_ctx, (duk_uint32_t) r_start);
81664  duk__append_u32(re_ctx, (duk_uint32_t) r_end);
81665  re_ctx->nranges++;
81666  r_start = t;
81667  r_end = t;
81668  }
81669  }
81670  DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
81671  duk__append_u32(re_ctx, (duk_uint32_t) r_start);
81672  duk__append_u32(re_ctx, (duk_uint32_t) r_end);
81673  re_ctx->nranges++;
81674  } else {
81675  DUK_DD(DUK_DDPRINT("direct, emit range: [%ld,%ld]", (long) r1, (long) r2));
81676  duk__append_u32(re_ctx, (duk_uint32_t) r1);
81677  duk__append_u32(re_ctx, (duk_uint32_t) r2);
81678  re_ctx->nranges++;
81679  }
81680 }
81681 
81682 /*
81683  * Parse regexp Disjunction. Most of regexp compilation happens here.
81684  *
81685  * Handles Disjunction, Alternative, and Term productions directly without
81686  * recursion. The only constructs requiring recursion are positive/negative
81687  * lookaheads, capturing parentheses, and non-capturing parentheses.
81688  *
81689  * The function determines whether the entire disjunction is a 'simple atom'
81690  * (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
81691  * returns the atom character length which is needed by the caller to keep
81692  * track of its own atom character length. A disjunction with more than one
81693  * alternative is never considered a simple atom (although in some cases
81694  * that might be the case).
81695  *
81696  * Return value: simple atom character length or < 0 if not a simple atom.
81697  * Appends the bytecode for the disjunction matcher to the end of the temp
81698  * buffer.
81699  *
81700  * Regexp top level structure is:
81701  *
81702  * Disjunction = Term*
81703  * | Term* | Disjunction
81704  *
81705  * Term = Assertion
81706  * | Atom
81707  * | Atom Quantifier
81708  *
81709  * An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
81710  *
81711  * Notes:
81712  *
81713  * * Tracking of the 'simple-ness' of the current atom vs. the entire
81714  * disjunction are separate matters. For instance, the disjunction
81715  * may be complex, but individual atoms may be simple. Furthermore,
81716  * simple quantifiers are used whenever possible, even if the
81717  * disjunction as a whole is complex.
81718  *
81719  * * The estimate of whether an atom is simple is conservative now,
81720  * and it would be possible to expand it. For instance, captures
81721  * cause the disjunction to be marked complex, even though captures
81722  * -can- be handled by simple quantifiers with some minor modifications.
81723  *
81724  * * Disjunction 'tainting' as 'complex' is handled at the end of the
81725  * main for loop collectively for atoms. Assertions, quantifiers,
81726  * and '|' tokens need to taint the result manually if necessary.
81727  * Assertions cannot add to result char length, only atoms (and
81728  * quantifiers) can; currently quantifiers will taint the result
81729  * as complex though.
81730  */
81731 
81732 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
81733  duk_unicode_re_ranges_digit,
81734  duk_unicode_re_ranges_white,
81735  duk_unicode_re_ranges_wordchar
81736 };
81737 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
81738  sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
81739  sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
81740  sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
81741 };
81742 
81743 DUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count) {
81744 #if 0
81745  DUK_ASSERT(re_op <= 0x7fUL);
81746  DUK_ASSERT(count <= 0x7fUL);
81747  duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
81748 #endif
81749  duk__append_reop(re_ctx, re_op);
81750  duk__append_7bit(re_ctx, count);
81751  duk__append_u16_list(re_ctx, ranges, count * 2);
81752 }
81753 
81754 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
81755  duk_int32_t atom_start_offset = -1; /* negative -> no atom matched on previous round */
81756  duk_int32_t atom_char_length = 0; /* negative -> complex atom */
81757  duk_uint32_t atom_start_captures = re_ctx->captures; /* value of re_ctx->captures at start of atom */
81758  duk_int32_t unpatched_disjunction_split = -1;
81759  duk_int32_t unpatched_disjunction_jump = -1;
81760  duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
81761  duk_int32_t res_charlen = 0; /* -1 if disjunction is complex, char length if simple */
81762  duk__re_disjunction_info tmp_disj;
81763 
81764  DUK_ASSERT(out_atom_info != NULL);
81765 
81766  if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
81767  DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
81768  }
81769  re_ctx->recursion_depth++;
81770 
81771 #if 0
81772  out_atom_info->start_captures = re_ctx->captures;
81773 #endif
81774 
81775  for (;;) {
81776  /* atom_char_length, atom_start_offset, atom_start_offset reflect the
81777  * atom matched on the previous loop. If a quantifier is encountered
81778  * on this loop, these are needed to handle the quantifier correctly.
81779  * new_atom_char_length etc are for the atom parsed on this round;
81780  * they're written to atom_char_length etc at the end of the round.
81781  */
81782  duk_int32_t new_atom_char_length; /* char length of the atom parsed in this loop */
81783  duk_int32_t new_atom_start_offset; /* bytecode start offset of the atom parsed in this loop
81784  * (allows quantifiers to copy the atom bytecode)
81785  */
81786  duk_uint32_t new_atom_start_captures; /* re_ctx->captures at the start of the atom parsed in this loop */
81787 
81788  duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
81789 
81790  DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
81791  (long) re_ctx->curr_token.t,
81792  (long) re_ctx->curr_token.num,
81793  (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
81794  (int) re_ctx->curr_token.num : (int) '?'));
81795 
81796  /* set by atom case clauses */
81797  new_atom_start_offset = -1;
81798  new_atom_char_length = -1;
81799  new_atom_start_captures = re_ctx->captures;
81800 
81801  switch (re_ctx->curr_token.t) {
81802  case DUK_RETOK_DISJUNCTION: {
81803  /*
81804  * The handling here is a bit tricky. If a previous '|' has been processed,
81805  * we have a pending split1 and a pending jump (for a previous match). These
81806  * need to be back-patched carefully. See docs for a detailed example.
81807  */
81808 
81809  /* patch pending jump and split */
81810  if (unpatched_disjunction_jump >= 0) {
81811  duk_uint32_t offset;
81812 
81813  DUK_ASSERT(unpatched_disjunction_split >= 0);
81814  offset = unpatched_disjunction_jump;
81815  offset += duk__insert_jump_offset(re_ctx,
81816  offset,
81817  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
81818  /* offset is now target of the pending split (right after jump) */
81819  duk__insert_jump_offset(re_ctx,
81820  unpatched_disjunction_split,
81821  offset - unpatched_disjunction_split);
81822  }
81823 
81824  /* add a new pending split to the beginning of the entire disjunction */
81825  (void) duk__insert_u32(re_ctx,
81826  entry_offset,
81827  DUK_REOP_SPLIT1); /* prefer direct execution */
81828  unpatched_disjunction_split = entry_offset + 1; /* +1 for opcode */
81829 
81830  /* add a new pending match jump for latest finished alternative */
81831  duk__append_reop(re_ctx, DUK_REOP_JUMP);
81832  unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
81833 
81834  /* 'taint' result as complex */
81835  res_charlen = -1;
81836  break;
81837  }
81838  case DUK_RETOK_QUANTIFIER: {
81839  if (atom_start_offset < 0) {
81840  DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
81841  }
81842  if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
81843  DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
81844  }
81845  if (atom_char_length >= 0) {
81846  /*
81847  * Simple atom
81848  *
81849  * If atom_char_length is zero, we'll have unbounded execution time for e.g.
81850  * /()*x/.exec('x'). We can't just skip the match because it might have some
81851  * side effects (for instance, if we allowed captures in simple atoms, the
81852  * capture needs to happen). The simple solution below is to force the
81853  * quantifier to match at most once, since the additional matches have no effect.
81854  *
81855  * With a simple atom there can be no capture groups, so no captures need
81856  * to be reset.
81857  */
81858  duk_int32_t atom_code_length;
81859  duk_uint32_t offset;
81860  duk_uint32_t qmin, qmax;
81861 
81862  qmin = re_ctx->curr_token.qmin;
81863  qmax = re_ctx->curr_token.qmax;
81864  if (atom_char_length == 0) {
81865  /* qmin and qmax will be 0 or 1 */
81866  if (qmin > 1) {
81867  qmin = 1;
81868  }
81869  if (qmax > 1) {
81870  qmax = 1;
81871  }
81872  }
81873 
81874  duk__append_reop(re_ctx, DUK_REOP_MATCH); /* complete 'sub atom' */
81875  atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - atom_start_offset);
81876 
81877  offset = atom_start_offset;
81878  if (re_ctx->curr_token.greedy) {
81879  offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
81880  offset += duk__insert_u32(re_ctx, offset, qmin);
81881  offset += duk__insert_u32(re_ctx, offset, qmax);
81882  offset += duk__insert_u32(re_ctx, offset, atom_char_length);
81883  offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
81884  } else {
81885  offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
81886  offset += duk__insert_u32(re_ctx, offset, qmin);
81887  offset += duk__insert_u32(re_ctx, offset, qmax);
81888  offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
81889  }
81890  DUK_UNREF(offset); /* silence scan-build warning */
81891  } else {
81892  /*
81893  * Complex atom
81894  *
81895  * The original code is used as a template, and removed at the end
81896  * (this differs from the handling of simple quantifiers).
81897  *
81898  * NOTE: there is no current solution for empty atoms in complex
81899  * quantifiers. This would need some sort of a 'progress' instruction.
81900  *
81901  * XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
81902  */
81903  duk_int32_t atom_code_length;
81904  duk_uint32_t atom_copies;
81905  duk_uint32_t tmp_qmin, tmp_qmax;
81906 
81907  /* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
81908  atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
81909  re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
81910  if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
81911  DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
81912  }
81913 
81914  /* wipe the capture range made by the atom (if any) */
81915  DUK_ASSERT(atom_start_captures <= re_ctx->captures);
81916  if (atom_start_captures != re_ctx->captures) {
81917  DUK_ASSERT(atom_start_captures < re_ctx->captures);
81918  DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
81919  (long) atom_start_captures, (long) re_ctx->captures));
81920 
81921  /* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
81922  duk__insert_u32(re_ctx, atom_start_offset, (re_ctx->captures - atom_start_captures) * 2);
81923  duk__insert_u32(re_ctx, atom_start_offset, (atom_start_captures + 1) * 2);
81924  duk__insert_u32(re_ctx, atom_start_offset, DUK_REOP_WIPERANGE);
81925  } else {
81926  DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
81927  (long) atom_start_captures));
81928  }
81929 
81930  atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
81931 
81932  /* insert the required matches (qmin) by copying the atom */
81933  tmp_qmin = re_ctx->curr_token.qmin;
81934  tmp_qmax = re_ctx->curr_token.qmax;
81935  while (tmp_qmin > 0) {
81936  duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
81937  tmp_qmin--;
81938  if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
81939  tmp_qmax--;
81940  }
81941  }
81942  DUK_ASSERT(tmp_qmin == 0);
81943 
81944  /* insert code for matching the remainder - infinite or finite */
81945  if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
81946  /* reuse last emitted atom for remaining 'infinite' quantifier */
81947 
81948  if (re_ctx->curr_token.qmin == 0) {
81949  /* Special case: original qmin was zero so there is nothing
81950  * to repeat. Emit an atom copy but jump over it here.
81951  */
81952  duk__append_reop(re_ctx, DUK_REOP_JUMP);
81953  duk__append_jump_offset(re_ctx, atom_code_length);
81954  duk__append_slice(re_ctx, atom_start_offset, atom_code_length);
81955  }
81956  if (re_ctx->curr_token.greedy) {
81957  duk__append_reop(re_ctx, DUK_REOP_SPLIT2); /* prefer jump */
81958  } else {
81959  duk__append_reop(re_ctx, DUK_REOP_SPLIT1); /* prefer direct */
81960  }
81961  duk__append_jump_offset(re_ctx, -atom_code_length - 1); /* -1 for opcode */
81962  } else {
81963  /*
81964  * The remaining matches are emitted as sequence of SPLITs and atom
81965  * copies; the SPLITs skip the remaining copies and match the sequel.
81966  * This sequence needs to be emitted starting from the last copy
81967  * because the SPLITs are variable length due to the variable length
81968  * skip offset. This causes a lot of memory copying now.
81969  *
81970  * Example structure (greedy, match maximum # atoms):
81971  *
81972  * SPLIT1 LSEQ
81973  * (atom)
81974  * SPLIT1 LSEQ ; <- the byte length of this instruction is needed
81975  * (atom) ; to encode the above SPLIT1 correctly
81976  * ...
81977  * LSEQ:
81978  */
81979  duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
81980  while (tmp_qmax > 0) {
81981  duk__insert_slice(re_ctx, offset, atom_start_offset, atom_code_length);
81982  if (re_ctx->curr_token.greedy) {
81983  duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1); /* prefer direct */
81984  } else {
81985  duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2); /* prefer jump */
81986  }
81987  duk__insert_jump_offset(re_ctx,
81988  offset + 1, /* +1 for opcode */
81989  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
81990  tmp_qmax--;
81991  }
81992  }
81993 
81994  /* remove the original 'template' atom */
81995  duk__remove_slice(re_ctx, atom_start_offset, atom_code_length);
81996  }
81997 
81998  /* 'taint' result as complex */
81999  res_charlen = -1;
82000  break;
82001  }
82002  case DUK_RETOK_ASSERT_START: {
82003  duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
82004  break;
82005  }
82006  case DUK_RETOK_ASSERT_END: {
82007  duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
82008  break;
82009  }
82010  case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
82011  duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
82012  break;
82013  }
82014  case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
82015  duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
82016  break;
82017  }
82018  case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
82019  case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
82020  duk_uint32_t offset;
82021  duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
82022  DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
82023 
82024  offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
82025  duk__parse_disjunction(re_ctx, 0, &tmp_disj);
82026  duk__append_reop(re_ctx, DUK_REOP_MATCH);
82027 
82028  (void) duk__insert_u32(re_ctx, offset, opcode);
82029  (void) duk__insert_jump_offset(re_ctx,
82030  offset + 1, /* +1 for opcode */
82031  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
82032 
82033  /* 'taint' result as complex -- this is conservative,
82034  * as lookaheads do not backtrack.
82035  */
82036  res_charlen = -1;
82037  break;
82038  }
82039  case DUK_RETOK_ATOM_PERIOD: {
82040  new_atom_char_length = 1;
82041  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82042  duk__append_reop(re_ctx, DUK_REOP_PERIOD);
82043  break;
82044  }
82045  case DUK_RETOK_ATOM_CHAR: {
82046  /* Note: successive characters could be joined into string matches
82047  * but this is not trivial (consider e.g. '/xyz+/); see docs for
82048  * more discussion.
82049  *
82050  * No support for \u{H+} yet. While only BMP Unicode escapes are
82051  * supported for RegExps at present, 'ch' may still be a non-BMP
82052  * codepoint if it is decoded straight from source text UTF-8.
82053  * There's no non-BMP support yet so this is handled simply by
82054  * matching the non-BMP character (which is custom behavior).
82055  */
82056  duk_uint32_t ch;
82057 
82058  new_atom_char_length = 1;
82059  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82060  duk__append_reop(re_ctx, DUK_REOP_CHAR);
82061  ch = re_ctx->curr_token.num;
82062  if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
82063  ch = duk_unicode_re_canonicalize_char(re_ctx->thr, ch);
82064  }
82065  duk__append_u32(re_ctx, ch);
82066  break;
82067  }
82068  case DUK_RETOK_ATOM_DIGIT:
82069  case DUK_RETOK_ATOM_NOT_DIGIT:
82070  case DUK_RETOK_ATOM_WHITE:
82071  case DUK_RETOK_ATOM_NOT_WHITE:
82072  case DUK_RETOK_ATOM_WORD_CHAR:
82073  case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
82074  duk_small_uint_t re_op;
82075  duk_small_uint_t idx;
82076 
82077  new_atom_char_length = 1;
82078  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82079 
82080  DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
82081  DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
82082  DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
82083  DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
82084  DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
82085  DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
82086  re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
82087 
82088  DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
82089  DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
82090  idx = (re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1;
82091  DUK_ASSERT(idx <= 2); /* Assume continuous token numbers; also checks negative underflow. */
82092 
82093  duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
82094  break;
82095  }
82096  case DUK_RETOK_ATOM_BACKREFERENCE: {
82097  duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
82098  if (backref > re_ctx->highest_backref) {
82099  re_ctx->highest_backref = backref;
82100  }
82101  new_atom_char_length = -1; /* mark as complex */
82102  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82103  duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
82104  duk__append_u32(re_ctx, backref);
82105  break;
82106  }
82107  case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
82108  duk_uint32_t cap;
82109 
82110  new_atom_char_length = -1; /* mark as complex (capture handling) */
82111  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82112  cap = ++re_ctx->captures;
82113  duk__append_reop(re_ctx, DUK_REOP_SAVE);
82114  duk__append_u32(re_ctx, cap * 2);
82115  duk__parse_disjunction(re_ctx, 0, &tmp_disj); /* retval (sub-atom char length) unused, tainted as complex above */
82116  duk__append_reop(re_ctx, DUK_REOP_SAVE);
82117  duk__append_u32(re_ctx, cap * 2 + 1);
82118  break;
82119  }
82120  case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
82121  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82122  duk__parse_disjunction(re_ctx, 0, &tmp_disj);
82123  new_atom_char_length = tmp_disj.charlen;
82124  break;
82125  }
82126  case DUK_RETOK_ATOM_START_CHARCLASS:
82127  case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
82128  /*
82129  * Range parsing is done with a special lexer function which calls
82130  * us for every range parsed. This is different from how rest of
82131  * the parsing works, but avoids a heavy, arbitrary size intermediate
82132  * value type to hold the ranges.
82133  *
82134  * Another complication is the handling of character ranges when
82135  * case insensitive matching is used (see docs for discussion).
82136  * The range handler callback given to the lexer takes care of this
82137  * as well.
82138  *
82139  * Note that duplicate ranges are not eliminated when parsing character
82140  * classes, so that canonicalization of
82141  *
82142  * [0-9a-fA-Fx-{]
82143  *
82144  * creates the result (note the duplicate ranges):
82145  *
82146  * [0-9A-FA-FX-Z{-{]
82147  *
82148  * where [x-{] is split as a result of canonicalization. The duplicate
82149  * ranges are not a semantics issue: they work correctly.
82150  */
82151 
82152  duk_uint32_t offset;
82153 
82154  DUK_DD(DUK_DDPRINT("character class"));
82155 
82156  /* insert ranges instruction, range count patched in later */
82157  new_atom_char_length = 1;
82158  new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
82159  duk__append_reop(re_ctx,
82160  (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
82161  DUK_REOP_RANGES : DUK_REOP_INVRANGES);
82162  offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx); /* patch in range count later */
82163 
82164  /* parse ranges until character class ends */
82165  re_ctx->nranges = 0; /* note: ctx-wide temporary */
82166  duk_lexer_parse_re_ranges(&re_ctx->lex, duk__generate_ranges, (void *) re_ctx);
82167 
82168  /* insert range count */
82169  duk__insert_u32(re_ctx, offset, re_ctx->nranges);
82170  break;
82171  }
82172  case DUK_RETOK_ATOM_END_GROUP: {
82173  if (expect_eof) {
82174  DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
82175  }
82176  goto done;
82177  }
82178  case DUK_RETOK_EOF: {
82179  if (!expect_eof) {
82180  DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
82181  }
82182  goto done;
82183  }
82184  default: {
82185  DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
82186  }
82187  }
82188 
82189  /* a complex (new) atom taints the result */
82190  if (new_atom_start_offset >= 0) {
82191  if (new_atom_char_length < 0) {
82192  res_charlen = -1;
82193  } else if (res_charlen >= 0) {
82194  /* only advance if not tainted */
82195  res_charlen += new_atom_char_length;
82196  }
82197  }
82198 
82199  /* record previous atom info in case next token is a quantifier */
82200  atom_start_offset = new_atom_start_offset;
82201  atom_char_length = new_atom_char_length;
82202  atom_start_captures = new_atom_start_captures;
82203  }
82204 
82205  done:
82206 
82207  /* finish up pending jump and split for last alternative */
82208  if (unpatched_disjunction_jump >= 0) {
82209  duk_uint32_t offset;
82210 
82211  DUK_ASSERT(unpatched_disjunction_split >= 0);
82212  offset = unpatched_disjunction_jump;
82213  offset += duk__insert_jump_offset(re_ctx,
82214  offset,
82215  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
82216  /* offset is now target of the pending split (right after jump) */
82217  duk__insert_jump_offset(re_ctx,
82218  unpatched_disjunction_split,
82219  offset - unpatched_disjunction_split);
82220  }
82221 
82222 #if 0
82223  out_atom_info->end_captures = re_ctx->captures;
82224 #endif
82225  out_atom_info->charlen = res_charlen;
82226  DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
82227  (long) out_atom_info->charlen));
82228 
82229  re_ctx->recursion_depth--;
82230 }
82231 
82232 /*
82233  * Flags parsing (see E5 Section 15.10.4.1).
82234  */
82235 
82236 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
82237  const duk_uint8_t *p;
82238  const duk_uint8_t *p_end;
82239  duk_uint32_t flags = 0;
82240 
82241  p = DUK_HSTRING_GET_DATA(h);
82242  p_end = p + DUK_HSTRING_GET_BYTELEN(h);
82243 
82244  /* Note: can be safely scanned as bytes (undecoded) */
82245 
82246  while (p < p_end) {
82247  duk_uint8_t c = *p++;
82248  switch (c) {
82249  case (duk_uint8_t) 'g': {
82250  if (flags & DUK_RE_FLAG_GLOBAL) {
82251  goto error;
82252  }
82253  flags |= DUK_RE_FLAG_GLOBAL;
82254  break;
82255  }
82256  case (duk_uint8_t) 'i': {
82257  if (flags & DUK_RE_FLAG_IGNORE_CASE) {
82258  goto error;
82259  }
82260  flags |= DUK_RE_FLAG_IGNORE_CASE;
82261  break;
82262  }
82263  case (duk_uint8_t) 'm': {
82264  if (flags & DUK_RE_FLAG_MULTILINE) {
82265  goto error;
82266  }
82267  flags |= DUK_RE_FLAG_MULTILINE;
82268  break;
82269  }
82270  default: {
82271  goto error;
82272  }
82273  }
82274  }
82275 
82276  return flags;
82277 
82278  error:
82279  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
82280  return 0; /* never here */
82281 }
82282 
82283 /*
82284  * Create escaped RegExp source (E5 Section 15.10.3).
82285  *
82286  * The current approach is to special case the empty RegExp
82287  * ('' -> '(?:)') and otherwise replace unescaped '/' characters
82288  * with '\/' regardless of where they occur in the regexp.
82289  *
82290  * Note that normalization does not seem to be necessary for
82291  * RegExp literals (e.g. '/foo/') because to be acceptable as
82292  * a RegExp literal, the text between forward slashes must
82293  * already match the escaping requirements (e.g. must not contain
82294  * unescaped forward slashes or be empty). Escaping IS needed
82295  * for expressions like 'new Regexp("...", "")' however.
82296  * Currently, we re-escape in either case.
82297  *
82298  * Also note that we process the source here in UTF-8 encoded
82299  * form. This is correct, because any non-ASCII characters are
82300  * passed through without change.
82301  */
82302 
82303 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
82304  duk_context *ctx = (duk_context *) thr;
82305  duk_hstring *h;
82306  const duk_uint8_t *p;
82307  duk_bufwriter_ctx bw_alloc;
82308  duk_bufwriter_ctx *bw;
82309  duk_uint8_t *q;
82310  duk_size_t i, n;
82311  duk_uint_fast8_t c_prev, c;
82312 
82313  h = duk_known_hstring(ctx, idx_pattern);
82314  p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
82315  n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
82316 
82317  if (n == 0) {
82318  duk_push_string(ctx, "(?:)");
82319  return;
82320  }
82321 
82322  bw = &bw_alloc;
82323  DUK_BW_INIT_PUSHBUF(thr, bw, n);
82324  q = DUK_BW_GET_PTR(thr, bw);
82325 
82326  c_prev = (duk_uint_fast8_t) 0;
82327 
82328  for (i = 0; i < n; i++) {
82329  c = p[i];
82330 
82331  q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
82332 
82333  if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
82334  /* Unescaped '/' ANYWHERE in the regexp (in disjunction,
82335  * inside a character class, ...) => same escape works.
82336  */
82337  *q++ = DUK_ASC_BACKSLASH;
82338  }
82339  *q++ = (duk_uint8_t) c;
82340 
82341  c_prev = c;
82342  }
82343 
82344  DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
82345  (void) duk_buffer_to_string(ctx, -1); /* Safe if input is safe. */
82346 
82347  /* [ ... escaped_source ] */
82348 }
82349 
82350 /*
82351  * Exposed regexp compilation primitive.
82352  *
82353  * Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
82354  * actual parsing. Handles generation of the compiled regexp header and the
82355  * "boilerplate" capture of the matching substring (save 0 and 1). Also does some
82356  * global level regexp checks after recursive compilation has finished.
82357  *
82358  * An escaped version of the regexp source, suitable for use as a RegExp instance
82359  * 'source' property (see E5 Section 15.10.3), is also left on the stack.
82360  *
82361  * Input stack: [ pattern flags ]
82362  * Output stack: [ bytecode escaped_source ] (both as strings)
82363  */
82364 
82365 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
82366  duk_context *ctx = (duk_context *) thr;
82367  duk_re_compiler_ctx re_ctx;
82368  duk_lexer_point lex_point;
82369  duk_hstring *h_pattern;
82370  duk_hstring *h_flags;
82371  duk__re_disjunction_info ign_disj;
82372 
82373  DUK_ASSERT(thr != NULL);
82374  DUK_ASSERT(ctx != NULL);
82375 
82376  /*
82377  * Args validation
82378  */
82379 
82380  /* TypeError if fails */
82381  h_pattern = duk_require_hstring_notsymbol(ctx, -2);
82382  h_flags = duk_require_hstring_notsymbol(ctx, -1);
82383 
82384  /*
82385  * Create normalized 'source' property (E5 Section 15.10.3).
82386  */
82387 
82388  /* [ ... pattern flags ] */
82389 
82390  duk__create_escaped_source(thr, -2);
82391 
82392  /* [ ... pattern flags escaped_source ] */
82393 
82394  /*
82395  * Init compilation context
82396  */
82397 
82398  /* [ ... pattern flags escaped_source buffer ] */
82399 
82400  DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
82401  DUK_LEXER_INITCTX(&re_ctx.lex); /* duplicate zeroing, expect for (possible) NULL inits */
82402  re_ctx.thr = thr;
82403  re_ctx.lex.thr = thr;
82404  re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
82405  re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
82406  re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
82407  re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
82408  re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
82409 
82410  DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
82411 
82412  DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
82413  (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
82414 
82415  /*
82416  * Init lexer
82417  */
82418 
82419  lex_point.offset = 0; /* expensive init, just want to fill window */
82420  lex_point.line = 1;
82421  DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
82422 
82423  /*
82424  * Compilation
82425  */
82426 
82427  DUK_DD(DUK_DDPRINT("starting regexp compilation"));
82428 
82429  duk__append_reop(&re_ctx, DUK_REOP_SAVE);
82430  duk__append_7bit(&re_ctx, 0);
82431  duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
82432  duk__append_reop(&re_ctx, DUK_REOP_SAVE);
82433  duk__append_7bit(&re_ctx, 1);
82434  duk__append_reop(&re_ctx, DUK_REOP_MATCH);
82435 
82436  /*
82437  * Check for invalid backreferences; note that it is NOT an error
82438  * to back-reference a capture group which has not yet been introduced
82439  * in the pattern (as in /\1(foo)/); in fact, the backreference will
82440  * always match! It IS an error to back-reference a capture group
82441  * which will never be introduced in the pattern. Thus, we can check
82442  * for such references only after parsing is complete.
82443  */
82444 
82445  if (re_ctx.highest_backref > re_ctx.captures) {
82446  DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
82447  }
82448 
82449  /*
82450  * Emit compiled regexp header: flags, ncaptures
82451  * (insertion order inverted on purpose)
82452  */
82453 
82454  duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
82455  duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
82456 
82457  /* [ ... pattern flags escaped_source buffer ] */
82458 
82459  DUK_BW_COMPACT(thr, &re_ctx.bw);
82460  (void) duk_buffer_to_string(ctx, -1); /* Safe because flags is at most 7 bit. */
82461 
82462  /* [ ... pattern flags escaped_source bytecode ] */
82463 
82464  /*
82465  * Finalize stack
82466  */
82467 
82468  duk_remove(ctx, -4); /* -> [ ... flags escaped_source bytecode ] */
82469  duk_remove(ctx, -3); /* -> [ ... escaped_source bytecode ] */
82470 
82471  DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
82472  (duk_tval *) duk_get_tval(ctx, -1), (duk_tval *) duk_get_tval(ctx, -2)));
82473 }
82474 
82475 /*
82476  * Create a RegExp instance (E5 Section 15.10.7).
82477  *
82478  * Note: the output stack left by duk_regexp_compile() is directly compatible
82479  * with the input here.
82480  *
82481  * Input stack: [ escaped_source bytecode ] (both as strings)
82482  * Output stack: [ RegExp ]
82483  */
82484 
82485 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
82486  duk_context *ctx = (duk_context *) thr;
82487  duk_hobject *h;
82488 
82489  /* [ ... escaped_source bytecode ] */
82490 
82491  duk_push_object(ctx);
82492  h = duk_known_hobject(ctx, -1);
82493  duk_insert(ctx, -3);
82494 
82495  /* [ ... regexp_object escaped_source bytecode ] */
82496 
82497  DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
82498  DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
82499 
82500  duk_xdef_prop_stridx_short(ctx, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
82501 
82502  /* [ ... regexp_object escaped_source ] */
82503 
82504  /* In ES2015 .source, and the .global, .multiline, etc flags are
82505  * inherited getters. Store the escaped source as an internal
82506  * property for the getter.
82507  */
82508 
82509  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
82510 
82511  /* [ ... regexp_object ] */
82512 
82513  duk_push_int(ctx, 0);
82514  duk_xdef_prop_stridx_short(ctx, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
82515 
82516  /* [ ... regexp_object ] */
82517 }
82518 
82519 #else /* DUK_USE_REGEXP_SUPPORT */
82520 
82521 /* regexp support disabled */
82522 
82523 #endif /* DUK_USE_REGEXP_SUPPORT */
82524 
82525 /* automatic undefs */
82526 #undef DUK__RE_BUFLEN
82527 #undef DUK__RE_INITIAL_BUFSIZE
82528 /*
82529  * Regexp executor.
82530  *
82531  * Safety: the Ecmascript executor should prevent user from reading and
82532  * replacing regexp bytecode. Even so, the executor must validate all
82533  * memory accesses etc. When an invalid access is detected (e.g. a 'save'
82534  * opcode to invalid, unallocated index) it should fail with an internal
82535  * error but not cause a segmentation fault.
82536  *
82537  * Notes:
82538  *
82539  * - Backtrack counts are limited to unsigned 32 bits but should
82540  * technically be duk_size_t for strings longer than 4G chars.
82541  * This also requires a regexp bytecode change.
82542  */
82543 
82544 /* #include duk_internal.h -> already included */
82545 
82546 #if defined(DUK_USE_REGEXP_SUPPORT)
82547 
82548 /*
82549  * Helpers for UTF-8 handling
82550  *
82551  * For bytecode readers the duk_uint32_t and duk_int32_t types are correct
82552  * because they're used for more than just codepoints.
82553  */
82554 
82555 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
82556  return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
82557 }
82558 
82559 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
82560  duk_uint32_t t;
82561 
82562  /* signed integer encoding needed to work with UTF-8 */
82563  t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
82564  if (t & 1) {
82565  return -((duk_int32_t) (t >> 1));
82566  } else {
82567  return (duk_int32_t) (t >> 1);
82568  }
82569 }
82570 
82571 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) {
82572  const duk_uint8_t *p;
82573 
82574  /* Note: allow backtracking from p == ptr_end */
82575  p = *ptr;
82576  if (p < ptr_start || p > ptr_end) {
82577  goto fail;
82578  }
82579 
82580  while (count > 0) {
82581  for (;;) {
82582  p--;
82583  if (p < ptr_start) {
82584  goto fail;
82585  }
82586  if ((*p & 0xc0) != 0x80) {
82587  /* utf-8 continuation bytes have the form 10xx xxxx */
82588  break;
82589  }
82590  }
82591  count--;
82592  }
82593  *ptr = p;
82594  return p;
82595 
82596  fail:
82597  DUK_ERROR_INTERNAL(thr);
82598  return NULL; /* never here */
82599 }
82600 
82601 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) {
82602  const duk_uint8_t *p;
82603 
82604  p = *ptr;
82605  if (p < ptr_start || p >= ptr_end) {
82606  goto fail;
82607  }
82608 
82609  while (count > 0) {
82610  for (;;) {
82611  p++;
82612 
82613  /* Note: if encoding ends by hitting end of input, we don't check that
82614  * the encoding is valid, we just assume it is.
82615  */
82616  if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
82617  /* utf-8 continuation bytes have the form 10xx xxxx */
82618  break;
82619  }
82620  }
82621  count--;
82622  }
82623 
82624  *ptr = p;
82625  return p;
82626 
82627  fail:
82628  DUK_ERROR_INTERNAL(thr);
82629  return NULL; /* never here */
82630 }
82631 
82632 /*
82633  * Helpers for dealing with the input string
82634  */
82635 
82636 /* Get a (possibly canonicalized) input character from current sp. The input
82637  * itself is never modified, and captures always record non-canonicalized
82638  * characters even in case-insensitive matching. Return <0 if out of input.
82639  */
82640 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
82641  duk_codepoint_t res;
82642 
82643  if (*sp >= re_ctx->input_end) {
82644  return -1;
82645  }
82646  res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
82647  if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
82648  res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
82649  }
82650  return res;
82651 }
82652 
82653 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) {
82654  return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
82655 }
82656 
82657 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
82658 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
82659  /* note: caller 'sp' is intentionally not updated here */
82660  (void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
82661  return duk__inp_get_cp(re_ctx, &sp);
82662 }
82663 
82664 /*
82665  * Regexp recursive matching function.
82666  *
82667  * Returns 'sp' on successful match (points to character after last matched one),
82668  * NULL otherwise.
82669  *
82670  * The C recursion depth limit check is only performed in this function, this
82671  * suffices because the function is present in all true recursion required by
82672  * regexp execution.
82673  */
82674 
82675 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) {
82676  if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
82677  DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
82678  }
82679  re_ctx->recursion_depth++;
82680 
82681  for (;;) {
82682  duk_small_int_t op;
82683 
82684  if (re_ctx->steps_count >= re_ctx->steps_limit) {
82685  DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
82686  }
82687  re_ctx->steps_count++;
82688 
82689  /* Opcodes are at most 7 bits now so they encode to one byte. If this
82690  * were not the case or 'pc' is invalid here (due to a bug etc) we'll
82691  * still fail safely through the switch default case.
82692  */
82693  DUK_ASSERT(pc[0] <= 0x7fU);
82694 #if 0
82695  op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
82696 #endif
82697  op = *pc++;
82698 
82699  DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
82700  (long) re_ctx->recursion_depth,
82701  (long) re_ctx->steps_count,
82702  (long) (pc - re_ctx->bytecode),
82703  (long) (sp - re_ctx->input),
82704  (long) op));
82705 
82706  switch (op) {
82707  case DUK_REOP_MATCH: {
82708  goto match;
82709  }
82710  case DUK_REOP_CHAR: {
82711  /*
82712  * Byte-based matching would be possible for case-sensitive
82713  * matching but not for case-insensitive matching. So, we
82714  * match by decoding the input and bytecode character normally.
82715  *
82716  * Bytecode characters are assumed to be already canonicalized.
82717  * Input characters are canonicalized automatically by
82718  * duk__inp_get_cp() if necessary.
82719  *
82720  * There is no opcode for matching multiple characters. The
82721  * regexp compiler has trouble joining strings efficiently
82722  * during compilation. See doc/regexp.rst for more discussion.
82723  */
82724  duk_codepoint_t c1, c2;
82725 
82726  c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
82727  DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
82728  c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
82729  c2 = duk__inp_get_cp(re_ctx, &sp);
82730  /* No need to check for c2 < 0 (end of input): because c1 >= 0, it
82731  * will fail the match below automatically and cause goto fail.
82732  */
82733 #if 0
82734  if (c2 < 0) {
82735  goto fail;
82736  }
82737 #endif
82738  DUK_ASSERT(c1 >= 0);
82739 
82740  DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
82741  if (c1 != c2) {
82742  goto fail;
82743  }
82744  break;
82745  }
82746  case DUK_REOP_PERIOD: {
82747  duk_codepoint_t c;
82748 
82749  c = duk__inp_get_cp(re_ctx, &sp);
82750  if (c < 0 || duk_unicode_is_line_terminator(c)) {
82751  /* E5 Sections 15.10.2.8, 7.3 */
82752  goto fail;
82753  }
82754  break;
82755  }
82756  case DUK_REOP_RANGES:
82757  case DUK_REOP_INVRANGES: {
82758  duk_uint32_t n;
82759  duk_codepoint_t c;
82760  duk_small_int_t match;
82761 
82762  n = duk__bc_get_u32(re_ctx, &pc);
82763  c = duk__inp_get_cp(re_ctx, &sp);
82764  if (c < 0) {
82765  goto fail;
82766  }
82767 
82768  match = 0;
82769  while (n) {
82770  duk_codepoint_t r1, r2;
82771  r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
82772  r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
82773  DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
82774  (long) n, (long) r1, (long) r2, (long) c));
82775  if (c >= r1 && c <= r2) {
82776  /* Note: don't bail out early, we must read all the ranges from
82777  * bytecode. Another option is to skip them efficiently after
82778  * breaking out of here. Prefer smallest code.
82779  */
82780  match = 1;
82781  }
82782  n--;
82783  }
82784 
82785  if (op == DUK_REOP_RANGES) {
82786  if (!match) {
82787  goto fail;
82788  }
82789  } else {
82790  DUK_ASSERT(op == DUK_REOP_INVRANGES);
82791  if (match) {
82792  goto fail;
82793  }
82794  }
82795  break;
82796  }
82797  case DUK_REOP_ASSERT_START: {
82798  duk_codepoint_t c;
82799 
82800  if (sp <= re_ctx->input) {
82801  break;
82802  }
82803  if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
82804  goto fail;
82805  }
82806  c = duk__inp_get_prev_cp(re_ctx, sp);
82807  if (duk_unicode_is_line_terminator(c)) {
82808  /* E5 Sections 15.10.2.8, 7.3 */
82809  break;
82810  }
82811  goto fail;
82812  }
82813  case DUK_REOP_ASSERT_END: {
82814  duk_codepoint_t c;
82815  const duk_uint8_t *tmp_sp;
82816 
82817  tmp_sp = sp;
82818  c = duk__inp_get_cp(re_ctx, &tmp_sp);
82819  if (c < 0) {
82820  break;
82821  }
82822  if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
82823  goto fail;
82824  }
82825  if (duk_unicode_is_line_terminator(c)) {
82826  /* E5 Sections 15.10.2.8, 7.3 */
82827  break;
82828  }
82829  goto fail;
82830  }
82831  case DUK_REOP_ASSERT_WORD_BOUNDARY:
82832  case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
82833  /*
82834  * E5 Section 15.10.2.6. The previous and current character
82835  * should -not- be canonicalized as they are now. However,
82836  * canonicalization does not affect the result of IsWordChar()
82837  * (which depends on Unicode characters never canonicalizing
82838  * into ASCII characters) so this does not matter.
82839  */
82840  duk_small_int_t w1, w2;
82841 
82842  if (sp <= re_ctx->input) {
82843  w1 = 0; /* not a wordchar */
82844  } else {
82845  duk_codepoint_t c;
82846  c = duk__inp_get_prev_cp(re_ctx, sp);
82847  w1 = duk_unicode_re_is_wordchar(c);
82848  }
82849  if (sp >= re_ctx->input_end) {
82850  w2 = 0; /* not a wordchar */
82851  } else {
82852  const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
82853  duk_codepoint_t c;
82854  c = duk__inp_get_cp(re_ctx, &tmp_sp);
82855  w2 = duk_unicode_re_is_wordchar(c);
82856  }
82857 
82858  if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
82859  if (w1 == w2) {
82860  goto fail;
82861  }
82862  } else {
82863  DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
82864  if (w1 != w2) {
82865  goto fail;
82866  }
82867  }
82868  break;
82869  }
82870  case DUK_REOP_JUMP: {
82871  duk_int32_t skip;
82872 
82873  skip = duk__bc_get_i32(re_ctx, &pc);
82874  pc += skip;
82875  break;
82876  }
82877  case DUK_REOP_SPLIT1: {
82878  /* split1: prefer direct execution (no jump) */
82879  const duk_uint8_t *sub_sp;
82880  duk_int32_t skip;
82881 
82882  skip = duk__bc_get_i32(re_ctx, &pc);
82883  sub_sp = duk__match_regexp(re_ctx, pc, sp);
82884  if (sub_sp) {
82885  sp = sub_sp;
82886  goto match;
82887  }
82888  pc += skip;
82889  break;
82890  }
82891  case DUK_REOP_SPLIT2: {
82892  /* split2: prefer jump execution (not direct) */
82893  const duk_uint8_t *sub_sp;
82894  duk_int32_t skip;
82895 
82896  skip = duk__bc_get_i32(re_ctx, &pc);
82897  sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
82898  if (sub_sp) {
82899  sp = sub_sp;
82900  goto match;
82901  }
82902  break;
82903  }
82904  case DUK_REOP_SQMINIMAL: {
82905  duk_uint32_t q, qmin, qmax;
82906  duk_int32_t skip;
82907  const duk_uint8_t *sub_sp;
82908 
82909  qmin = duk__bc_get_u32(re_ctx, &pc);
82910  qmax = duk__bc_get_u32(re_ctx, &pc);
82911  skip = duk__bc_get_i32(re_ctx, &pc);
82912  DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
82913  (unsigned long) qmin, (unsigned long) qmax, (long) skip));
82914 
82915  q = 0;
82916  while (q <= qmax) {
82917  if (q >= qmin) {
82918  sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
82919  if (sub_sp) {
82920  sp = sub_sp;
82921  goto match;
82922  }
82923  }
82924  sub_sp = duk__match_regexp(re_ctx, pc, sp);
82925  if (!sub_sp) {
82926  break;
82927  }
82928  sp = sub_sp;
82929  q++;
82930  }
82931  goto fail;
82932  }
82933  case DUK_REOP_SQGREEDY: {
82934  duk_uint32_t q, qmin, qmax, atomlen;
82935  duk_int32_t skip;
82936  const duk_uint8_t *sub_sp;
82937 
82938  qmin = duk__bc_get_u32(re_ctx, &pc);
82939  qmax = duk__bc_get_u32(re_ctx, &pc);
82940  atomlen = duk__bc_get_u32(re_ctx, &pc);
82941  skip = duk__bc_get_i32(re_ctx, &pc);
82942  DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
82943  (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
82944 
82945  q = 0;
82946  while (q < qmax) {
82947  sub_sp = duk__match_regexp(re_ctx, pc, sp);
82948  if (!sub_sp) {
82949  break;
82950  }
82951  sp = sub_sp;
82952  q++;
82953  }
82954  while (q >= qmin) {
82955  sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
82956  if (sub_sp) {
82957  sp = sub_sp;
82958  goto match;
82959  }
82960  if (q == qmin) {
82961  break;
82962  }
82963 
82964  /* Note: if atom were to contain e.g. captures, we would need to
82965  * re-match the atom to get correct captures. Simply quantifiers
82966  * do not allow captures in their atom now, so this is not an issue.
82967  */
82968 
82969  DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
82970  (long) atomlen));
82971  sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
82972  q--;
82973  }
82974  goto fail;
82975  }
82976  case DUK_REOP_SAVE: {
82977  duk_uint32_t idx;
82978  const duk_uint8_t *old;
82979  const duk_uint8_t *sub_sp;
82980 
82981  idx = duk__bc_get_u32(re_ctx, &pc);
82982  if (idx >= re_ctx->nsaved) {
82983  /* idx is unsigned, < 0 check is not necessary */
82984  DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
82985  goto internal_error;
82986  }
82987  old = re_ctx->saved[idx];
82988  re_ctx->saved[idx] = sp;
82989  sub_sp = duk__match_regexp(re_ctx, pc, sp);
82990  if (sub_sp) {
82991  sp = sub_sp;
82992  goto match;
82993  }
82994  re_ctx->saved[idx] = old;
82995  goto fail;
82996  }
82997  case DUK_REOP_WIPERANGE: {
82998  /* Wipe capture range and save old values for backtracking.
82999  *
83000  * XXX: this typically happens with a relatively small idx_count.
83001  * It might be useful to handle cases where the count is small
83002  * (say <= 8) by saving the values in stack instead. This would
83003  * reduce memory churn and improve performance, at the cost of a
83004  * slightly higher code footprint.
83005  */
83006  duk_uint32_t idx_start, idx_count;
83007 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
83008  duk_uint32_t idx_end, idx;
83009 #endif
83010  duk_uint8_t **range_save;
83011  const duk_uint8_t *sub_sp;
83012 
83013  idx_start = duk__bc_get_u32(re_ctx, &pc);
83014  idx_count = duk__bc_get_u32(re_ctx, &pc);
83015  DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
83016  (long) idx_start, (long) idx_count,
83017  (long) idx_start, (long) (idx_start + idx_count - 1),
83018  (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
83019  if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
83020  /* idx is unsigned, < 0 check is not necessary */
83021  DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
83022  (long) idx_start, (long) idx_count));
83023  goto internal_error;
83024  }
83025  DUK_ASSERT(idx_count > 0);
83026 
83027  duk_require_stack((duk_context *) re_ctx->thr, 1);
83028  range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero((duk_context *) re_ctx->thr,
83029  sizeof(duk_uint8_t *) * idx_count);
83030  DUK_ASSERT(range_save != NULL);
83031  DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
83032 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
83033  idx_end = idx_start + idx_count;
83034  for (idx = idx_start; idx < idx_end; idx++) {
83035  re_ctx->saved[idx] = NULL;
83036  }
83037 #else
83038  DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
83039 #endif
83040 
83041  sub_sp = duk__match_regexp(re_ctx, pc, sp);
83042  if (sub_sp) {
83043  /* match: keep wiped/resaved values */
83044  DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
83045  (long) idx_start, (long) (idx_start + idx_count - 1),
83046  (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
83047  duk_pop((duk_context *) re_ctx->thr);
83048  sp = sub_sp;
83049  goto match;
83050  }
83051 
83052  /* fail: restore saves */
83053  DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
83054  (long) idx_start, (long) (idx_start + idx_count - 1),
83055  (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
83056  DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
83057  (const void *) range_save,
83058  sizeof(duk_uint8_t *) * idx_count);
83059  duk_pop((duk_context *) re_ctx->thr);
83060  goto fail;
83061  }
83062  case DUK_REOP_LOOKPOS:
83063  case DUK_REOP_LOOKNEG: {
83064  /*
83065  * Needs a save of multiple saved[] entries depending on what range
83066  * may be overwritten. Because the regexp parser does no such analysis,
83067  * we currently save the entire saved array here. Lookaheads are thus
83068  * a bit expensive. Note that the saved array is not needed for just
83069  * the lookahead sub-match, but for the matching of the entire sequel.
83070  *
83071  * The temporary save buffer is pushed on to the valstack to handle
83072  * errors correctly. Each lookahead causes a C recursion and pushes
83073  * more stuff on the value stack. If the C recursion limit is less
83074  * than the value stack spare, there is no need to check the stack.
83075  * We do so regardless, just in case.
83076  */
83077 
83078  duk_int32_t skip;
83079  duk_uint8_t **full_save;
83080  const duk_uint8_t *sub_sp;
83081 
83082  DUK_ASSERT(re_ctx->nsaved > 0);
83083 
83084  duk_require_stack((duk_context *) re_ctx->thr, 1);
83085  full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero((duk_context *) re_ctx->thr,
83086  sizeof(duk_uint8_t *) * re_ctx->nsaved);
83087  DUK_ASSERT(full_save != NULL);
83088  DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
83089 
83090  skip = duk__bc_get_i32(re_ctx, &pc);
83091  sub_sp = duk__match_regexp(re_ctx, pc, sp);
83092  if (op == DUK_REOP_LOOKPOS) {
83093  if (!sub_sp) {
83094  goto lookahead_fail;
83095  }
83096  } else {
83097  if (sub_sp) {
83098  goto lookahead_fail;
83099  }
83100  }
83101  sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
83102  if (sub_sp) {
83103  /* match: keep saves */
83104  duk_pop((duk_context *) re_ctx->thr);
83105  sp = sub_sp;
83106  goto match;
83107  }
83108 
83109  /* fall through */
83110 
83111  lookahead_fail:
83112  /* fail: restore saves */
83113  DUK_MEMCPY((void *) re_ctx->saved,
83114  (const void *) full_save,
83115  sizeof(duk_uint8_t *) * re_ctx->nsaved);
83116  duk_pop((duk_context *) re_ctx->thr);
83117  goto fail;
83118  }
83119  case DUK_REOP_BACKREFERENCE: {
83120  /*
83121  * Byte matching for back-references would be OK in case-
83122  * sensitive matching. In case-insensitive matching we need
83123  * to canonicalize characters, so back-reference matching needs
83124  * to be done with codepoints instead. So, we just decode
83125  * everything normally here, too.
83126  *
83127  * Note: back-reference index which is 0 or higher than
83128  * NCapturingParens (= number of capturing parens in the
83129  * -entire- regexp) is a compile time error. However, a
83130  * backreference referring to a valid capture which has
83131  * not matched anything always succeeds! See E5 Section
83132  * 15.10.2.9, step 5, sub-step 3.
83133  */
83134  duk_uint32_t idx;
83135  const duk_uint8_t *p;
83136 
83137  idx = duk__bc_get_u32(re_ctx, &pc);
83138  idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
83139  if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
83140  /* regexp compiler should catch these */
83141  DUK_D(DUK_DPRINT("internal error, backreference index insane"));
83142  goto internal_error;
83143  }
83144  if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
83145  /* capture is 'undefined', always matches! */
83146  DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
83147  (long) idx, (long) (idx + 1)));
83148  break;
83149  }
83150  DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
83151 
83152  p = re_ctx->saved[idx];
83153  while (p < re_ctx->saved[idx+1]) {
83154  duk_codepoint_t c1, c2;
83155 
83156  /* Note: not necessary to check p against re_ctx->input_end:
83157  * the memory access is checked by duk__inp_get_cp(), while
83158  * valid compiled regexps cannot write a saved[] entry
83159  * which points to outside the string.
83160  */
83161  c1 = duk__inp_get_cp(re_ctx, &p);
83162  DUK_ASSERT(c1 >= 0);
83163  c2 = duk__inp_get_cp(re_ctx, &sp);
83164  /* No need for an explicit c2 < 0 check: because c1 >= 0,
83165  * the comparison will always fail if c2 < 0.
83166  */
83167 #if 0
83168  if (c2 < 0) {
83169  goto fail;
83170  }
83171 #endif
83172  if (c1 != c2) {
83173  goto fail;
83174  }
83175  }
83176  break;
83177  }
83178  default: {
83179  DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
83180  goto internal_error;
83181  }
83182  }
83183  }
83184 
83185  match:
83186  re_ctx->recursion_depth--;
83187  return sp;
83188 
83189  fail:
83190  re_ctx->recursion_depth--;
83191  return NULL;
83192 
83193  internal_error:
83194  DUK_ERROR_INTERNAL(re_ctx->thr);
83195  return NULL; /* never here */
83196 }
83197 
83198 /*
83199  * Exposed matcher function which provides the semantics of RegExp.prototype.exec().
83200  *
83201  * RegExp.prototype.test() has the same semantics as exec() but does not return the
83202  * result object (which contains the matching string and capture groups). Currently
83203  * there is no separate test() helper, so a temporary result object is created and
83204  * discarded if test() is needed. This is intentional, to save code space.
83205  *
83206  * Input stack: [ ... re_obj input ]
83207  * Output stack: [ ... result ]
83208  */
83209 
83210 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
83211  duk_context *ctx = (duk_context *) thr;
83212  duk_re_matcher_ctx re_ctx;
83213  duk_hobject *h_regexp;
83214  duk_hstring *h_bytecode;
83215  duk_hstring *h_input;
83216  duk_uint8_t *p_buf;
83217  const duk_uint8_t *pc;
83218  const duk_uint8_t *sp;
83219  duk_small_int_t match = 0;
83220  duk_small_int_t global;
83221  duk_uint_fast32_t i;
83222  double d;
83223  duk_uint32_t char_offset;
83224 
83225  DUK_ASSERT(thr != NULL);
83226  DUK_ASSERT(ctx != NULL);
83227 
83228  DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
83229  (duk_tval *) duk_get_tval(ctx, -2),
83230  (duk_tval *) duk_get_tval(ctx, -1)));
83231 
83232  /*
83233  * Regexp instance check, bytecode check, input coercion.
83234  *
83235  * See E5 Section 15.10.6.
83236  */
83237 
83238  /* TypeError if wrong; class check, see E5 Section 15.10.6 */
83239  h_regexp = duk_require_hobject_with_class(ctx, -2, DUK_HOBJECT_CLASS_REGEXP);
83240  DUK_ASSERT(h_regexp != NULL);
83241  DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
83242  DUK_UNREF(h_regexp);
83243 
83244  h_input = duk_to_hstring(ctx, -1);
83245  DUK_ASSERT(h_input != NULL);
83246 
83247  duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
83248  h_bytecode = duk_require_hstring(ctx, -1); /* no regexp instance should exist without a non-configurable bytecode property */
83249  DUK_ASSERT(h_bytecode != NULL);
83250 
83251  /*
83252  * Basic context initialization.
83253  *
83254  * Some init values are read from the bytecode header
83255  * whose format is (UTF-8 codepoints):
83256  *
83257  * uint flags
83258  * uint nsaved (even, 2n+2 where n = num captures)
83259  */
83260 
83261  /* [ ... re_obj input bc ] */
83262 
83263  DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
83264 
83265  re_ctx.thr = thr;
83266  re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
83267  re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
83268  re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
83269  re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
83270  re_ctx.saved = NULL;
83271  re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
83272  re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
83273 
83274  /* read header */
83275  pc = re_ctx.bytecode;
83276  re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
83277  re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
83278  re_ctx.bytecode = pc;
83279 
83280  DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
83281  global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
83282 
83283  DUK_ASSERT(re_ctx.nsaved >= 2);
83284  DUK_ASSERT((re_ctx.nsaved % 2) == 0);
83285 
83286  p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved); /* rely on zeroing */
83287  DUK_UNREF(p_buf);
83288  re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
83289  DUK_ASSERT(re_ctx.saved != NULL);
83290 
83291  /* [ ... re_obj input bc saved_buf ] */
83292 
83293 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
83294  for (i = 0; i < re_ctx.nsaved; i++) {
83295  re_ctx.saved[i] = (duk_uint8_t *) NULL;
83296  }
83297 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
83298  /* buffer is automatically zeroed */
83299 #else
83300  DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
83301 #endif
83302 
83303  DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
83304  (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
83305  (long) re_ctx.steps_limit));
83306 
83307  /*
83308  * Get starting character offset for match, and initialize 'sp' based on it.
83309  *
83310  * Note: lastIndex is non-configurable so it must be present (we check the
83311  * internal class of the object above, so we know it is). User code can set
83312  * its value to an arbitrary (garbage) value though; E5 requires that lastIndex
83313  * be coerced to a number before using. The code below works even if the
83314  * property is missing: the value will then be coerced to zero.
83315  *
83316  * Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
83317  * For instance, ToInteger(+Infinity) = +Infinity. We track the match offset
83318  * as an integer, but pre-check it to be inside the 32-bit range before the loop.
83319  * If not, the check in E5 Section 15.10.6.2, step 9.a applies.
83320  */
83321 
83322  /* XXX: lastIndex handling produces a lot of asm */
83323 
83324  /* [ ... re_obj input bc saved_buf ] */
83325 
83326  duk_get_prop_stridx_short(ctx, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
83327  (void) duk_to_int(ctx, -1); /* ToInteger(lastIndex) */
83328  d = duk_get_number(ctx, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
83329  duk_pop(ctx);
83330 
83331  if (global) {
83332  if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
83333  /* match fail */
83334  char_offset = 0; /* not really necessary */
83335  DUK_ASSERT(match == 0);
83336  goto match_over;
83337  }
83338  char_offset = (duk_uint32_t) d;
83339  } else {
83340  /* lastIndex must be ignored for non-global regexps, but get the
83341  * value for (theoretical) side effects. No side effects can
83342  * really occur, because lastIndex is a normal property and is
83343  * always non-configurable for RegExp instances.
83344  */
83345  char_offset = (duk_uint32_t) 0;
83346  }
83347 
83348  sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
83349 
83350  /*
83351  * Match loop.
83352  *
83353  * Try matching at different offsets until match found or input exhausted.
83354  */
83355 
83356  /* [ ... re_obj input bc saved_buf ] */
83357 
83358  DUK_ASSERT(match == 0);
83359 
83360  for (;;) {
83361  /* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
83362  DUK_ASSERT_DISABLE(char_offset >= 0);
83363  DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
83364 
83365  /* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
83366  DUK_ASSERT(re_ctx.recursion_depth == 0);
83367 
83368  DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
83369  (long) char_offset, (const void *) sp,
83370  (const void *) re_ctx.input, (const void *) re_ctx.input_end));
83371 
83372  /*
83373  * Note:
83374  *
83375  * - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
83376  * conditions; a longjmp() will terminate the entire matching process.
83377  *
83378  * - Clearing saved[] is not necessary because backtracking does it
83379  *
83380  * - Backtracking also rewinds ctx.recursion back to zero, unless an
83381  * internal/limit error occurs (which causes a longjmp())
83382  *
83383  * - If we supported anchored matches, we would break out here
83384  * unconditionally; however, Ecmascript regexps don't have anchored
83385  * matches. It might make sense to implement a fast bail-out if
83386  * the regexp begins with '^' and sp is not 0: currently we'll just
83387  * run through the entire input string, trivially failing the match
83388  * at every non-zero offset.
83389  */
83390 
83391  if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
83392  DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
83393  match = 1;
83394  break;
83395  }
83396 
83397  /* advance by one character (code point) and one char_offset */
83398  char_offset++;
83399  if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
83400  /*
83401  * Note:
83402  *
83403  * - Intentionally attempt (empty) match at char_offset == k_input->clen
83404  *
83405  * - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
83406  * -> no need or use for a negative check
83407  */
83408 
83409  DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
83410  break;
83411  }
83412 
83413  /* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
83414  (void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
83415  }
83416 
83417  match_over:
83418 
83419  /*
83420  * Matching complete, create result array or return a 'null'. Update lastIndex
83421  * if necessary. See E5 Section 15.10.6.2.
83422  *
83423  * Because lastIndex is a character (not byte) offset, we need the character
83424  * length of the match which we conveniently get as a side effect of interning
83425  * the matching substring (0th index of result array).
83426  *
83427  * saved[0] start pointer (~ byte offset) of current match
83428  * saved[1] end pointer (~ byte offset) of current match (exclusive)
83429  * char_offset start character offset of current match (-> .index of result)
83430  * char_end_offset end character offset (computed below)
83431  */
83432 
83433  /* [ ... re_obj input bc saved_buf ] */
83434 
83435  if (match) {
83436 #if defined(DUK_USE_ASSERTIONS)
83437  duk_hobject *h_res;
83438 #endif
83439  duk_uint32_t char_end_offset = 0;
83440 
83441  DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
83442 
83443  DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
83444  DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
83445 
83446  /* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
83447  * advantage of now. The array is not compacted either, as regexp match
83448  * objects are usually short lived.
83449  */
83450 
83451  duk_push_array(ctx);
83452 
83453 #if defined(DUK_USE_ASSERTIONS)
83454  h_res = duk_require_hobject(ctx, -1);
83455  DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
83456  DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
83457  DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
83458 #endif
83459 
83460  /* [ ... re_obj input bc saved_buf res_obj ] */
83461 
83462  duk_push_u32(ctx, char_offset);
83463  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INDEX);
83464 
83465  duk_dup_m4(ctx);
83466  duk_xdef_prop_stridx_short_wec(ctx, -2, DUK_STRIDX_INPUT);
83467 
83468  for (i = 0; i < re_ctx.nsaved; i += 2) {
83469  /* Captures which are undefined have NULL pointers and are returned
83470  * as 'undefined'. The same is done when saved[] pointers are insane
83471  * (this should, of course, never happen in practice).
83472  */
83473  if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
83474  duk_push_lstring(ctx,
83475  (const char *) re_ctx.saved[i],
83476  (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
83477  if (i == 0) {
83478  /* Assumes that saved[0] and saved[1] are always
83479  * set by regexp bytecode (if not, char_end_offset
83480  * will be zero). Also assumes clen reflects the
83481  * correct char length.
83482  */
83483  char_end_offset = char_offset + (duk_uint32_t) duk_get_length(ctx, -1); /* add charlen */
83484  }
83485  } else {
83486  duk_push_undefined(ctx);
83487  }
83488 
83489  /* [ ... re_obj input bc saved_buf res_obj val ] */
83490  duk_put_prop_index(ctx, -2, i / 2);
83491  }
83492 
83493  /* [ ... re_obj input bc saved_buf res_obj ] */
83494 
83495  /* NB: 'length' property is automatically updated by the array setup loop */
83496 
83497  if (global) {
83498  /* global regexp: lastIndex updated on match */
83499  duk_push_u32(ctx, char_end_offset);
83500  duk_put_prop_stridx_short(ctx, -6, DUK_STRIDX_LAST_INDEX);
83501  } else {
83502  /* non-global regexp: lastIndex never updated on match */
83503  ;
83504  }
83505  } else {
83506  /*
83507  * No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
83508  * of 'global' flag of the RegExp. In particular, if lastIndex is invalid
83509  * initially, it is reset to zero.
83510  */
83511 
83512  DUK_DDD(DUK_DDDPRINT("regexp does not match"));
83513 
83514  duk_push_null(ctx);
83515 
83516  /* [ ... re_obj input bc saved_buf res_obj ] */
83517 
83518  duk_push_int(ctx, 0);
83519  duk_put_prop_stridx_short(ctx, -6, DUK_STRIDX_LAST_INDEX);
83520  }
83521 
83522  /* [ ... re_obj input bc saved_buf res_obj ] */
83523 
83524  duk_insert(ctx, -5);
83525 
83526  /* [ ... res_obj re_obj input bc saved_buf ] */
83527 
83528  duk_pop_n(ctx, 4);
83529 
83530  /* [ ... res_obj ] */
83531 
83532  /* XXX: these last tricks are unnecessary if the function is made
83533  * a genuine native function.
83534  */
83535 }
83536 
83537 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
83538  duk__regexp_match_helper(thr, 0 /*force_global*/);
83539 }
83540 
83541 /* This variant is needed by String.prototype.split(); it needs to perform
83542  * global-style matching on a cloned RegExp which is potentially non-global.
83543  */
83544 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
83545  duk__regexp_match_helper(thr, 1 /*force_global*/);
83546 }
83547 
83548 #else /* DUK_USE_REGEXP_SUPPORT */
83549 
83550 /* regexp support disabled */
83551 
83552 #endif /* DUK_USE_REGEXP_SUPPORT */
83553 /*
83554  * Self tests to ensure execution environment is sane. Intended to catch
83555  * compiler/platform problems which cannot be detected at compile time.
83556  */
83557 
83558 /* #include duk_internal.h -> already included */
83559 
83560 #if defined(DUK_USE_SELF_TESTS)
83561 
83562 /*
83563  * Unions and structs for self tests
83564  */
83565 
83566 typedef union {
83567  double d;
83568  duk_uint8_t x[8];
83569 } duk__test_double_union;
83570 
83571 /* Self test failed. Expects a local variable 'error_count' to exist. */
83572 #define DUK__FAILED(msg) do { \
83573  DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
83574  error_count++; \
83575  } while (0)
83576 
83577 #define DUK__DBLUNION_CMP_TRUE(a,b) do { \
83578  if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
83579  DUK__FAILED("double union compares false (expected true)"); \
83580  } \
83581  } while (0)
83582 
83583 #define DUK__DBLUNION_CMP_FALSE(a,b) do { \
83584  if (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
83585  DUK__FAILED("double union compares true (expected false)"); \
83586  } \
83587  } while (0)
83588 
83589 typedef union {
83590  duk_uint32_t i;
83591  duk_uint8_t x[8];
83592 } duk__test_u32_union;
83593 
83594 #if defined(DUK_USE_INTEGER_LE)
83595 #define DUK__U32_INIT(u, a, b, c, d) do { \
83596  (u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
83597  } while (0)
83598 #elif defined(DUK_USE_INTEGER_ME)
83599 #error integer mixed endian not supported now
83600 #elif defined(DUK_USE_INTEGER_BE)
83601 #define DUK__U32_INIT(u, a, b, c, d) do { \
83602  (u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
83603  } while (0)
83604 #else
83605 #error unknown integer endianness
83606 #endif
83607 
83608 #if defined(DUK_USE_DOUBLE_LE)
83609 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
83610  (u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
83611  (u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
83612  } while (0)
83613 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
83614  ((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
83615  (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
83616 #elif defined(DUK_USE_DOUBLE_ME)
83617 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
83618  (u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
83619  (u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
83620  } while (0)
83621 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
83622  ((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
83623  (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
83624 #elif defined(DUK_USE_DOUBLE_BE)
83625 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
83626  (u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
83627  (u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
83628  } while (0)
83629 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
83630  ((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
83631  (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
83632 #else
83633 #error unknown double endianness
83634 #endif
83635 
83636 /*
83637  * Various sanity checks for typing
83638  */
83639 
83640 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
83641  duk_uint_t error_count = 0;
83642 
83643  if (!(sizeof(duk_int8_t) == 1 &&
83644  sizeof(duk_uint8_t) == 1 &&
83645  sizeof(duk_int16_t) == 2 &&
83646  sizeof(duk_uint16_t) == 2 &&
83647  sizeof(duk_int32_t) == 4 &&
83648  sizeof(duk_uint32_t) == 4)) {
83649  DUK__FAILED("duk_(u)int{8,16,32}_t size");
83650  }
83651 #if defined(DUK_USE_64BIT_OPS)
83652  if (!(sizeof(duk_int64_t) == 8 &&
83653  sizeof(duk_uint64_t) == 8)) {
83654  DUK__FAILED("duk_(u)int64_t size");
83655  }
83656 #endif
83657 
83658  if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
83659  /* Some internal code now assumes that all duk_uint_t values
83660  * can be expressed with a duk_size_t.
83661  */
83662  DUK__FAILED("duk_size_t is smaller than duk_uint_t");
83663  }
83664  if (!(sizeof(duk_int_t) >= 4)) {
83665  DUK__FAILED("duk_int_t is not 32 bits");
83666  }
83667 
83668  return error_count;
83669 }
83670 
83671 /*
83672  * Packed tval sanity
83673  */
83674 
83675 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
83676  duk_uint_t error_count = 0;
83677 
83678 #if defined(DUK_USE_PACKED_TVAL)
83679  if (sizeof(void *) > 4) {
83680  DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
83681  }
83682 #endif
83683 
83684  return error_count;
83685 }
83686 
83687 /*
83688  * Two's complement arithmetic.
83689  */
83690 
83691 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
83692  duk_uint_t error_count = 0;
83693  volatile int test;
83694  test = -1;
83695 
83696  /* Note that byte order doesn't affect this test: all bytes in
83697  * 'test' will be 0xFF for two's complement.
83698  */
83699  if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
83700  DUK__FAILED("two's complement arithmetic");
83701  }
83702 
83703  return error_count;
83704 }
83705 
83706 /*
83707  * Byte order. Important to self check, because on some exotic platforms
83708  * there is no actual detection but rather assumption based on platform
83709  * defines.
83710  */
83711 
83712 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
83713  duk_uint_t error_count = 0;
83714  duk__test_u32_union u1;
83715  duk__test_double_union u2;
83716 
83717  /*
83718  * >>> struct.pack('>d', 102030405060).encode('hex')
83719  * '4237c17c6dc40000'
83720  */
83721 
83722  DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
83723  DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
83724 
83725  if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
83726  DUK__FAILED("duk_uint32_t byte order");
83727  }
83728 
83729  if (u2.d != (double) 102030405060.0) {
83730  DUK__FAILED("double byte order");
83731  }
83732 
83733  return error_count;
83734 }
83735 
83736 /*
83737  * DUK_BSWAP macros
83738  */
83739 
83740 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
83741  duk_uint_t error_count = 0;
83742  duk_uint32_t x32;
83743  duk_uint16_t x16;
83744  duk_double_union du;
83745  duk_double_t du_diff;
83746 
83747  x16 = 0xbeefUL;
83748  x16 = DUK_BSWAP16(x16);
83749  if (x16 != (duk_uint16_t) 0xefbeUL) {
83750  DUK__FAILED("DUK_BSWAP16");
83751  }
83752 
83753  x32 = 0xdeadbeefUL;
83754  x32 = DUK_BSWAP32(x32);
83755  if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
83756  DUK__FAILED("DUK_BSWAP32");
83757  }
83758 
83759  /* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
83760  * (2.008366013071895,)
83761  */
83762 
83763  du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
83764  du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
83765  DUK_DBLUNION_DOUBLE_NTOH(&du);
83766  du_diff = du.d - 2.008366013071895;
83767 #if 0
83768  DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
83769 #endif
83770  if (du_diff > 1e-15) {
83771  /* Allow very small lenience because some compilers won't parse
83772  * exact IEEE double constants (happened in matrix testing with
83773  * Linux gcc-4.8 -m32 at least).
83774  */
83775 #if 0
83776  DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
83777  (unsigned int) du.uc[0], (unsigned int) du.uc[1],
83778  (unsigned int) du.uc[2], (unsigned int) du.uc[3],
83779  (unsigned int) du.uc[4], (unsigned int) du.uc[5],
83780  (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
83781 #endif
83782  DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
83783  }
83784 
83785  return error_count;
83786 }
83787 
83788 /*
83789  * Basic double / byte union memory layout.
83790  */
83791 
83792 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
83793  duk_uint_t error_count = 0;
83794 
83795  if (sizeof(duk__test_double_union) != 8) {
83796  DUK__FAILED("invalid union size");
83797  }
83798 
83799  return error_count;
83800 }
83801 
83802 /*
83803  * Union aliasing, see misc/clang_aliasing.c.
83804  */
83805 
83806 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
83807  /* This testcase fails when Emscripten-generated code runs on Firefox.
83808  * It's not an issue because the failure should only affect packed
83809  * duk_tval representation, which is not used with Emscripten.
83810  */
83811 #if defined(DUK_USE_PACKED_TVAL)
83812  duk_uint_t error_count = 0;
83813  duk__test_double_union a, b;
83814 
83815  /* Test signaling NaN and alias assignment in all endianness combinations.
83816  */
83817 
83818  /* little endian */
83819  a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
83820  a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
83821  b = a;
83822  DUK__DBLUNION_CMP_TRUE(&a, &b);
83823 
83824  /* big endian */
83825  a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
83826  a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
83827  b = a;
83828  DUK__DBLUNION_CMP_TRUE(&a, &b);
83829 
83830  /* mixed endian */
83831  a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
83832  a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
83833  b = a;
83834  DUK__DBLUNION_CMP_TRUE(&a, &b);
83835 
83836  return error_count;
83837 #else
83838  DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
83839  return 0;
83840 #endif
83841 }
83842 
83843 /*
83844  * Zero sign, see misc/tcc_zerosign2.c.
83845  */
83846 
83847 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
83848  duk_uint_t error_count = 0;
83849  duk__test_double_union a, b;
83850 
83851  a.d = 0.0;
83852  b.d = -a.d;
83853  DUK__DBLUNION_CMP_FALSE(&a, &b);
83854 
83855  return error_count;
83856 }
83857 
83858 /*
83859  * Rounding mode: Duktape assumes round-to-nearest, check that this is true.
83860  * If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
83861  * but we don't want to rely on that header; and even if we did, it's good
83862  * to ensure the rounding actually works.
83863  */
83864 
83865 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
83866  duk_uint_t error_count = 0;
83867  duk__test_double_union a, b, c;
83868 
83869 #if 0
83870  /* Include <fenv.h> and test manually; these trigger failures: */
83871  fesetround(FE_UPWARD);
83872  fesetround(FE_DOWNWARD);
83873  fesetround(FE_TOWARDZERO);
83874 
83875  /* This is the default and passes. */
83876  fesetround(FE_TONEAREST);
83877 #endif
83878 
83879  /* Rounding tests check that none of the other modes (round to
83880  * +Inf, round to -Inf, round to zero) can be active:
83881  * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
83882  */
83883 
83884  /* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
83885  * Round to nearest: 1.0
83886  * Round to +Inf: 1.0 + ulp
83887  * Round to -Inf: 1.0
83888  * Round to zero: 1.0
83889  * => Correct result eliminates round to +Inf.
83890  */
83891  DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
83892  DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
83893  DUK_MEMSET((void *) &c, 0, sizeof(c));
83894  c.d = a.d + b.d;
83895  if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
83896  DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
83897  (unsigned int) c.x[0], (unsigned int) c.x[1],
83898  (unsigned int) c.x[2], (unsigned int) c.x[3],
83899  (unsigned int) c.x[4], (unsigned int) c.x[5],
83900  (unsigned int) c.x[6], (unsigned int) c.x[7]));
83901  DUK__FAILED("invalid result from 1.0 + 0.5ulp");
83902  }
83903 
83904  /* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
83905  * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
83906  * Round to +Inf: 1.0 + 2*ulp
83907  * Round to -Inf: 1.0 + ulp
83908  * Round to zero: 1.0 + ulp
83909  * => Correct result eliminates round to -Inf and round to zero.
83910  */
83911  DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
83912  DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
83913  DUK_MEMSET((void *) &c, 0, sizeof(c));
83914  c.d = a.d + b.d;
83915  if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
83916  DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
83917  (unsigned int) c.x[0], (unsigned int) c.x[1],
83918  (unsigned int) c.x[2], (unsigned int) c.x[3],
83919  (unsigned int) c.x[4], (unsigned int) c.x[5],
83920  (unsigned int) c.x[6], (unsigned int) c.x[7]));
83921  DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
83922  }
83923 
83924  /* Could do negative number testing too, but the tests above should
83925  * differentiate between IEEE 754 rounding modes.
83926  */
83927  return error_count;
83928 }
83929 
83930 /*
83931  * fmod(): often a portability issue in embedded or bare platform targets.
83932  * Check for at least minimally correct behavior. Unlike some other math
83933  * functions (like cos()) Duktape relies on fmod() internally too.
83934  */
83935 
83936 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
83937  duk_uint_t error_count = 0;
83938  duk__test_double_union u1, u2;
83939 
83940  /* fmod() with integer argument and exponent 2^32 is used by e.g.
83941  * ToUint32() and some Duktape internals.
83942  */
83943  u1.d = DUK_FMOD(10.0, 4294967296.0);
83944  u2.d = 10.0;
83945  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83946 
83947  u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
83948  u2.d = 10.0;
83949  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83950 
83951  u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
83952  u2.d = 10.0;
83953  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83954 
83955  /* C99 behavior is for fmod() result sign to mathc argument sign. */
83956  u1.d = DUK_FMOD(-10.0, 4294967296.0);
83957  u2.d = -10.0;
83958  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83959 
83960  u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
83961  u2.d = -10.0;
83962  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83963 
83964  u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
83965  u2.d = -10.0;
83966  DUK__DBLUNION_CMP_TRUE(&u1, &u2);
83967 
83968  return error_count;
83969 }
83970 
83971 /*
83972  * Struct size/alignment if platform requires it
83973  *
83974  * There are some compiler specific struct padding pragmas etc in use, this
83975  * selftest ensures they're correctly detected and used.
83976  */
83977 
83978 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
83979  duk_uint_t error_count = 0;
83980 
83981 #if (DUK_USE_ALIGN_BY == 4)
83982  if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
83983  DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
83984  }
83985 #elif (DUK_USE_ALIGN_BY == 8)
83986  if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
83987  DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
83988  }
83989 #elif (DUK_USE_ALIGN_BY == 1)
83990  /* no check */
83991 #else
83992 #error invalid DUK_USE_ALIGN_BY
83993 #endif
83994  return error_count;
83995 }
83996 
83997 /*
83998  * 64-bit arithmetic
83999  *
84000  * There are some platforms/compilers where 64-bit types are available
84001  * but don't work correctly. Test for known cases.
84002  */
84003 
84004 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
84005  duk_uint_t error_count = 0;
84006 #if defined(DUK_USE_64BIT_OPS)
84007  volatile duk_int64_t i;
84008  volatile duk_double_t d;
84009 
84010  /* Catch a double-to-int64 cast issue encountered in practice. */
84011  d = 2147483648.0;
84012  i = (duk_int64_t) d;
84013  if (i != 0x80000000LL) {
84014  DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
84015  }
84016 #else
84017  /* nop */
84018 #endif
84019  return error_count;
84020 }
84021 
84022 /*
84023  * Casting
84024  */
84025 
84026 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
84027  /*
84028  * https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
84029  */
84030 
84031  duk_uint_t error_count = 0;
84032 
84033  duk_double_t d1, d2;
84034  duk_small_uint_t u;
84035 
84036  duk_double_t d1v, d2v;
84037  duk_small_uint_t uv;
84038 
84039  /* Test without volatiles */
84040 
84041  d1 = 1.0;
84042  u = (duk_small_uint_t) d1;
84043  d2 = (duk_double_t) u;
84044 
84045  if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
84046  DUK__FAILED("double to duk_small_uint_t cast failed");
84047  }
84048 
84049  /* Same test with volatiles */
84050 
84051  d1v = 1.0;
84052  uv = (duk_small_uint_t) d1v;
84053  d2v = (duk_double_t) uv;
84054 
84055  if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
84056  DUK__FAILED("double to duk_small_uint_t cast failed");
84057  }
84058 
84059  return error_count;
84060 }
84061 
84062 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
84063  /*
84064  * This test fails on an exotic ARM target; double-to-uint
84065  * cast is incorrectly clamped to -signed- int highest value.
84066  *
84067  * https://github.com/svaarala/duktape/issues/336
84068  */
84069 
84070  duk_uint_t error_count = 0;
84071  duk_double_t dv;
84072  duk_uint32_t uv;
84073 
84074  dv = 3735928559.0; /* 0xdeadbeef in decimal */
84075  uv = (duk_uint32_t) dv;
84076 
84077  if (uv != 0xdeadbeefUL) {
84078  DUK__FAILED("double to duk_uint32_t cast failed");
84079  }
84080 
84081  return error_count;
84082 }
84083 
84084 /*
84085  * Minimal test of user supplied allocation functions
84086  *
84087  * - Basic alloc + realloc + free cycle
84088  *
84089  * - Realloc to significantly larger size to (hopefully) trigger a
84090  * relocation and check that relocation copying works
84091  */
84092 
84093 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
84094  duk_realloc_function realloc_func,
84095  duk_free_function free_func,
84096  void *udata) {
84097  duk_uint_t error_count = 0;
84098  void *ptr;
84099  void *new_ptr;
84100  duk_small_int_t i, j;
84101  unsigned char x;
84102 
84103  if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
84104  return 0;
84105  }
84106 
84107  for (i = 1; i <= 256; i++) {
84108  ptr = alloc_func(udata, i);
84109  if (ptr == NULL) {
84110  DUK_D(DUK_DPRINT("alloc failed, ignore"));
84111  continue; /* alloc failed, ignore */
84112  }
84113  for (j = 0; j < i; j++) {
84114  ((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
84115  }
84116  new_ptr = realloc_func(udata, ptr, 1024);
84117  if (new_ptr == NULL) {
84118  DUK_D(DUK_DPRINT("realloc failed, ignore"));
84119  free_func(udata, ptr);
84120  continue; /* realloc failed, ignore */
84121  }
84122  ptr = new_ptr;
84123  for (j = 0; j < i; j++) {
84124  x = ((unsigned char *) ptr)[j];
84125  if (x != (unsigned char) (0x80 + j)) {
84126  DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
84127  (long) j, (unsigned long) x));
84128  DUK__FAILED("byte compare after realloc");
84129  break;
84130  }
84131  }
84132  free_func(udata, ptr);
84133  }
84134 
84135  return error_count;
84136 }
84137 
84138 /*
84139  * Self test main
84140  */
84141 
84142 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
84143  duk_realloc_function realloc_func,
84144  duk_free_function free_func,
84145  void *udata) {
84146  duk_uint_t error_count = 0;
84147 
84148  DUK_D(DUK_DPRINT("self test starting"));
84149 
84150  error_count += duk__selftest_types();
84151  error_count += duk__selftest_packed_tval();
84152  error_count += duk__selftest_twos_complement();
84153  error_count += duk__selftest_byte_order();
84154  error_count += duk__selftest_bswap_macros();
84155  error_count += duk__selftest_double_union_size();
84156  error_count += duk__selftest_double_aliasing();
84157  error_count += duk__selftest_double_zero_sign();
84158  error_count += duk__selftest_double_rounding();
84159  error_count += duk__selftest_fmod();
84160  error_count += duk__selftest_struct_align();
84161  error_count += duk__selftest_64bit_arithmetic();
84162  error_count += duk__selftest_cast_double_to_small_uint();
84163  error_count += duk__selftest_cast_double_to_uint32();
84164  error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
84165 
84166  DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
84167 
84168  return error_count;
84169 }
84170 
84171 #endif /* DUK_USE_SELF_TESTS */
84172 
84173 /* automatic undefs */
84174 #undef DUK__DBLUNION_CMP_FALSE
84175 #undef DUK__DBLUNION_CMP_TRUE
84176 #undef DUK__DOUBLE_COMPARE
84177 #undef DUK__DOUBLE_INIT
84178 #undef DUK__FAILED
84179 #undef DUK__U32_INIT
84180 /* #include duk_internal.h -> already included */
84181 
84182 #if defined(DUK_USE_FASTINT)
84183 
84184 /*
84185  * Manually optimized double-to-fastint downgrade check.
84186  *
84187  * This check has a large impact on performance, especially for fastint
84188  * slow paths, so must be changed carefully. The code should probably be
84189  * optimized for the case where the result does not fit into a fastint,
84190  * to minimize the penalty for "slow path code" dealing with fractions etc.
84191  *
84192  * At least on one tested soft float ARM platform double-to-int64 coercion
84193  * is very slow (and sometimes produces incorrect results, see self tests).
84194  * This algorithm combines a fastint compatibility check and extracting the
84195  * integer value from an IEEE double for setting the tagged fastint. For
84196  * other platforms a more naive approach might be better.
84197  *
84198  * See doc/fastint.rst for details.
84199  */
84200 
84201 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
84202  duk_double_union du;
84203  duk_int64_t i;
84204  duk_small_int_t expt;
84205  duk_small_int_t shift;
84206 
84207  /* XXX: optimize for packed duk_tval directly? */
84208 
84209  du.d = x;
84210  i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
84211  expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
84212  shift = expt - 1023;
84213 
84214  if (shift >= 0 && shift <= 46) { /* exponents 1023 to 1069 */
84215  duk_int64_t t;
84216 
84217  if (((0x000fffffffffffffLL >> shift) & i) == 0) {
84218  t = i | 0x0010000000000000LL; /* implicit leading one */
84219  t = t & 0x001fffffffffffffLL;
84220  t = t >> (52 - shift);
84221  if (i < 0) {
84222  t = -t;
84223  }
84224  DUK_TVAL_SET_FASTINT(tv, t);
84225  return;
84226  }
84227  } else if (shift == -1023) { /* exponent 0 */
84228  if (i >= 0 && (i & 0x000fffffffffffffLL) == 0) {
84229  /* Note: reject negative zero. */
84230  DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
84231  return;
84232  }
84233  } else if (shift == 47) { /* exponent 1070 */
84234  if (i < 0 && (i & 0x000fffffffffffffLL) == 0) {
84235  DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
84236  return;
84237  }
84238  }
84239 
84240  DUK_TVAL_SET_DOUBLE(tv, x);
84241  return;
84242 }
84243 
84244 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
84245  duk_tval_set_number_chkfast_fast(tv, x);
84246 }
84247 
84248 /*
84249  * Manually optimized number-to-double conversion
84250  */
84251 
84252 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
84253 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
84254  duk_double_union du;
84255  duk_uint64_t t;
84256 
84257  t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
84258  if ((t >> 48) != DUK_TAG_FASTINT) {
84259  return tv->d;
84260  } else if (t & 0x0000800000000000ULL) {
84261  t = (duk_uint64_t) (-((duk_int64_t) t)); /* avoid unary minus on unsigned */
84262  t = t & 0x0000ffffffffffffULL; /* negative */
84263  t |= 0xc330000000000000ULL;
84264  DUK_DBLUNION_SET_UINT64(&du, t);
84265  return du.d + 4503599627370496.0; /* 1 << 52 */
84266  } else if (t != 0) {
84267  t &= 0x0000ffffffffffffULL; /* positive */
84268  t |= 0x4330000000000000ULL;
84269  DUK_DBLUNION_SET_UINT64(&du, t);
84270  return du.d - 4503599627370496.0; /* 1 << 52 */
84271  } else {
84272  return 0.0; /* zero */
84273  }
84274 }
84275 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
84276 
84277 #if 0 /* unused */
84278 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
84279 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
84280  duk_double_union du;
84281  duk_uint64_t t;
84282 
84283  DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
84284 
84285  if (tv->t == DUK_TAG_FASTINT) {
84286  if (tv->v.fi >= 0) {
84287  t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
84288  DUK_DBLUNION_SET_UINT64(&du, t);
84289  return du.d - 4503599627370496.0; /* 1 << 52 */
84290  } else {
84291  t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
84292  DUK_DBLUNION_SET_UINT64(&du, t);
84293  return du.d + 4503599627370496.0; /* 1 << 52 */
84294  }
84295  } else {
84296  return tv->v.d;
84297  }
84298 }
84299 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
84300 #endif /* 0 */
84301 
84302 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
84303 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
84304  duk_double_union du;
84305  duk_uint64_t t;
84306 
84307  DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
84308 
84309  if (tv->v.fi >= 0) {
84310  t = 0x4330000000000000ULL | (duk_uint64_t) tv->v.fi;
84311  DUK_DBLUNION_SET_UINT64(&du, t);
84312  return du.d - 4503599627370496.0; /* 1 << 52 */
84313  } else {
84314  t = 0xc330000000000000ULL | (duk_uint64_t) (-tv->v.fi);
84315  DUK_DBLUNION_SET_UINT64(&du, t);
84316  return du.d + 4503599627370496.0; /* 1 << 52 */
84317  }
84318 }
84319 #endif /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
84320 
84321 #endif /* DUK_USE_FASTINT */
84322 /*
84323  * Unicode support tables automatically generated during build.
84324  */
84325 
84326 /* #include duk_internal.h -> already included */
84327 
84328 /*
84329  * Unicode tables containing ranges of Unicode characters in a
84330  * packed format. These tables are used to match non-ASCII
84331  * characters of complex productions by resorting to a linear
84332  * range-by-range comparison. This is very slow, but is expected
84333  * to be very rare in practical Ecmascript source code, and thus
84334  * compactness is most important.
84335  *
84336  * The tables are matched using uni_range_match() and the format
84337  * is described in tools/extract_chars.py.
84338  */
84339 
84340 #if defined(DUK_USE_SOURCE_NONBMP)
84341 /* IdentifierStart production with ASCII excluded */
84342 /* duk_unicode_ids_noa[] */
84343 /*
84344  * Automatically generated by extract_chars.py, do not edit!
84345  */
84346 
84347 const duk_uint8_t duk_unicode_ids_noa[1036] = {
84348 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
84349 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
84350 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
84351 101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,
84352 240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,
84353 2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,
84354 47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,
84355 38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,
84356 41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,
84357 34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,
84358 85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,
84359 63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,
84360 240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,
84361 15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,
84362 240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,
84363 43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,
84364 15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,
84365 112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,
84366 29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,
84367 146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,
84368 224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,
84369 253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,
84370 35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,
84371 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
84372 240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,
84373 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
84374 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
84375 207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,
84376 223,13,79,33,242,31,16,240,47,11,111,22,191,14,63,20,87,36,241,207,142,240,
84377 79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,
84378 3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,
84379 1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,107,240,
84380 62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,47,9,240,
84381 207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,102,32,35,
84382 46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,240,67,242,
84383 127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,27,244,127,
84384 10,255,224,122,243,15,17,15,254,11,79,41,255,152,47,21,240,48,242,63,14,
84385 255,226,100,255,226,140,245,143,95,240,63,180,255,233,176,255,227,33,255,
84386 238,197,255,225,57,255,240,1,10,223,254,18,184,240,255,99,240,239,4,242,15,
84387 2,63,17,240,86,240,63,254,38,79,53,192,243,76,243,32,241,31,255,0,6,223,
84388 240,95,254,30,95,255,0,20,1,31,254,175,47,91,108,72,137,255,240,0,101,175,
84389 69,47,55,33,48,49,51,43,32,38,47,49,35,55,38,47,12,35,36,32,70,47,254,4,99,
84390 240,146,240,146,240,242,240,146,240,242,240,146,240,242,240,146,240,242,
84391 240,146,127,254,242,143,181,242,223,52,255,227,176,50,240,178,18,3,2,146,
84392 50,2,7,5,2,2,2,34,18,3,2,2,2,2,2,18,3,50,98,50,50,2,146,240,22,34,66,240,
84393 31,255,0,0,56,255,240,9,92,159,27,255,239,39,207,206,63,255,0,5,116,255,
84394 240,1,133,47,254,17,0,
84395 };
84396 #else
84397 /* IdentifierStart production with ASCII and non-BMP excluded */
84398 /* duk_unicode_ids_noabmp[] */
84399 /*
84400  * Automatically generated by extract_chars.py, do not edit!
84401  */
84402 
84403 const duk_uint8_t duk_unicode_ids_noabmp[625] = {
84404 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
84405 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
84406 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
84407 101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,
84408 240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,
84409 2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,
84410 47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,
84411 38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,
84412 41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,
84413 34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,
84414 85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,
84415 63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,
84416 240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,
84417 15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,
84418 240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,
84419 43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,
84420 15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,
84421 112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,
84422 29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,
84423 146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,
84424 224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,
84425 253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,
84426 35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,
84427 240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,
84428 240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,
84429 95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,
84430 207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,
84431 207,73,69,53,53,50,0,
84432 };
84433 #endif
84434 
84435 #if defined(DUK_USE_SOURCE_NONBMP)
84436 /* IdentifierStart production with Letter and ASCII excluded */
84437 /* duk_unicode_ids_m_let_noa[] */
84438 /*
84439  * Automatically generated by extract_chars.py, do not edit!
84440  */
84441 
84442 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
84443 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
84444 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
84445 };
84446 #else
84447 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
84448 /* duk_unicode_ids_m_let_noabmp[] */
84449 /*
84450  * Automatically generated by extract_chars.py, do not edit!
84451  */
84452 
84453 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
84454 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
84455 249,0,
84456 };
84457 #endif
84458 
84459 #if defined(DUK_USE_SOURCE_NONBMP)
84460 /* IdentifierPart production with IdentifierStart and ASCII excluded */
84461 /* duk_unicode_idp_m_ids_noa[] */
84462 /*
84463  * Automatically generated by extract_chars.py, do not edit!
84464  */
84465 
84466 const duk_uint8_t duk_unicode_idp_m_ids_noa[530] = {
84467 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
84468 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
84469 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
84470 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
84471 97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
84472 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,
84473 242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,
84474 244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,
84475 111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,
84476 241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,
84477 244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,
84478 241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,
84479 35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,
84480 255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,
84481 79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,
84482 208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
84483 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
84484 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47,
84485 39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68,
84486 183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77,
84487 159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255,
84488 226,57,114,127,2,159,42,240,98,223,255,0,60,157,159,120,79,45,111,11,159,
84489 254,46,191,30,240,35,255,240,3,191,225,255,240,0,59,164,69,151,54,241,3,
84490 248,98,255,228,125,242,47,254,15,79,39,95,34,144,240,0,240,132,46,255,228,
84491 68,98,240,19,98,18,79,254,121,150,245,246,105,255,240,192,105,175,224,0,
84492 };
84493 #else
84494 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
84495 /* duk_unicode_idp_m_ids_noabmp[] */
84496 /*
84497  * Automatically generated by extract_chars.py, do not edit!
84498  */
84499 
84500 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357] = {
84501 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
84502 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
84503 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
84504 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
84505 97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
84506 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,
84507 242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,
84508 244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,
84509 111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,
84510 241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,
84511 244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,
84512 241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,
84513 35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,
84514 255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,
84515 79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,
84516 208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
84517 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
84518 };
84519 #endif
84520 
84521 /*
84522  * Case conversion tables generated using tools/extract_caseconv.py.
84523  */
84524 
84525 /* duk_unicode_caseconv_uc[] */
84526 /* duk_unicode_caseconv_lc[] */
84527 
84528 /*
84529  * Automatically generated by extract_caseconv.py, do not edit!
84530  */
84531 
84532 const duk_uint8_t duk_unicode_caseconv_uc[1386] = {
84533 144,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
84534 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
84535 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,9,252,9,248,6,28,131,4,
84536 33,4,62,0,62,16,32,124,64,124,96,48,249,0,249,64,129,243,1,243,129,3,232,3,
84537 233,1,135,216,7,218,4,15,184,15,221,2,31,114,31,200,8,62,236,63,180,8,125,
84538 224,127,224,16,251,208,255,80,33,247,193,255,160,67,246,3,247,0,135,244,7,
84539 246,1,15,240,15,244,2,33,112,33,96,32,73,160,73,108,104,176,192,176,1,121,
84540 104,0,133,2,106,183,1,58,10,31,232,63,228,38,162,1,1,1,0,48,2,102,2,100,12,
84541 4,232,4,228,64,10,88,10,81,112,23,160,23,144,96,48,96,48,64,128,104,64,104,
84542 1,128,218,0,217,130,1,206,1,205,16,3,190,3,188,36,7,228,7,224,160,17,24,17,
84543 16,144,36,112,36,96,160,110,32,110,0,128,246,64,246,6,2,48,130,48,17,4,139,
84544 4,138,54,9,132,9,130,28,19,68,19,65,128,240,8,240,4,177,234,17,234,6,3,234,
84545 35,235,33,11,26,11,25,193,150,64,150,64,50,44,236,44,235,5,76,131,76,128,
84546 94,154,6,154,0,117,57,29,57,16,122,115,58,115,35,244,239,84,239,32,169,223,
84547 233,223,130,211,200,211,200,2,167,151,167,150,21,79,107,79,104,8,112,26,
84548 208,26,192,64,56,160,56,128,192,113,128,113,1,128,249,0,248,130,2,128,1,
84549 166,4,7,240,7,238,8,177,204,177,200,16,96,49,0,48,224,128,110,64,110,1,1,
84550 51,83,213,2,0,48,35,192,35,176,64,77,32,50,192,139,73,196,49,193,127,48,2,
84551 212,14,112,3,252,5,224,4,196,1,36,5,252,1,76,6,0,9,12,6,72,6,68,6,84,7,216,
84552 6,100,6,96,6,104,8,244,6,120,8,128,6,160,6,156,6,252,7,220,7,116,6,56,7,
84553 204,7,196,9,64,177,188,9,68,177,180,9,72,177,192,9,76,6,4,9,80,6,24,9,100,
84554 6,60,9,108,6,64,9,114,158,172,9,128,6,76,9,134,158,176,9,140,6,80,9,150,
84555 158,52,9,160,6,92,9,172,177,136,9,178,158,180,9,196,177,184,9,200,6,116,9,
84556 212,6,124,9,244,177,144,10,30,158,196,10,32,6,184,10,36,9,16,10,48,9,20,10,
84557 72,6,220,10,118,158,200,10,122,158,192,13,20,14,100,13,220,13,216,14,176,
84558 14,24,15,8,14,140,15,48,14,48,15,64,14,72,15,68,14,96,15,84,14,152,15,88,
84559 14,128,15,92,15,60,15,192,14,104,15,196,14,132,15,200,15,228,15,204,13,252,
84560 15,212,14,84,19,60,19,0,114,0,16,72,114,4,16,80,114,8,16,120,114,20,16,136,
84561 114,24,16,168,114,28,17,136,114,34,153,40,117,230,157,244,117,244,177,140,
84562 122,108,121,128,126,248,14,100,127,148,127,176,133,56,132,200,134,16,134,
84563 12,177,132,177,128,177,148,8,232,177,152,8,248,179,204,179,202,158,50,158,
84564 46,173,78,158,207,48,6,252,0,166,0,166,2,147,1,94,0,39,0,248,64,9,64,97,
84565 128,114,24,28,200,24,64,24,8,29,134,7,74,6,16,6,2,11,15,2,154,130,169,15,
84566 75,64,9,0,102,35,210,240,2,160,24,64,244,196,0,174,6,20,61,51,0,44,129,133,
84567 15,77,64,8,32,87,195,234,16,29,40,24,152,250,150,7,74,6,38,6,0,62,169,129,
84568 210,129,137,129,128,143,171,96,116,160,98,96,104,67,240,16,248,64,28,200,
84569 252,12,62,18,7,50,63,5,15,133,1,204,143,193,195,225,96,115,35,240,144,248,
84570 96,28,200,252,44,62,26,7,50,63,13,15,135,1,204,143,195,195,225,224,115,35,
84571 241,16,248,64,28,200,252,76,62,18,7,50,63,21,15,133,1,204,143,197,195,225,
84572 96,115,35,241,144,248,96,28,200,252,108,62,26,7,50,63,29,15,135,1,204,143,
84573 199,195,225,224,115,35,242,16,249,64,28,200,252,140,62,82,7,50,63,37,15,
84574 149,1,204,143,201,195,229,96,115,35,242,144,249,96,28,200,252,172,62,90,7,
84575 50,63,45,15,151,1,204,143,203,195,229,224,115,35,243,16,249,64,28,200,252,
84576 204,62,82,7,50,63,53,15,149,1,204,143,205,195,229,96,115,35,243,144,249,96,
84577 28,200,252,236,62,90,7,50,63,61,15,151,1,204,143,207,195,229,224,115,35,
84578 244,16,251,64,28,200,253,12,62,210,7,50,63,69,15,181,1,204,143,209,195,237,
84579 96,115,35,244,144,251,96,28,200,253,44,62,218,7,50,63,77,15,183,1,204,143,
84580 211,195,237,224,115,35,245,16,251,64,28,200,253,76,62,210,7,50,63,85,15,
84581 181,1,204,143,213,195,237,96,115,35,245,144,251,96,28,200,253,108,62,218,7,
84582 50,63,93,15,183,1,204,143,215,195,237,224,115,35,246,80,253,208,28,200,253,
84583 156,7,34,7,50,63,105,1,195,1,204,143,219,64,114,32,104,67,246,248,28,136,
84584 26,16,28,200,253,228,7,34,7,50,63,133,15,229,1,204,143,225,192,114,224,115,
84585 35,248,144,28,72,28,200,254,52,7,46,6,132,63,143,129,203,129,161,1,204,143,
84586 230,64,114,224,115,35,250,88,28,200,24,64,24,0,254,158,7,50,6,16,6,2,63,
84587 173,1,204,129,161,15,235,224,115,32,97,0,104,67,252,88,29,40,24,64,24,0,
84588 255,30,7,74,6,16,6,2,63,201,1,208,129,137,143,243,64,116,160,104,67,252,
84589 248,29,40,24,64,26,16,255,148,63,244,7,50,63,231,1,212,129,204,143,250,64,
84590 113,224,115,35,254,208,29,72,26,16,255,190,7,82,6,132,7,50,63,249,1,212,
84591 129,204,253,128,64,8,192,8,223,96,48,2,48,2,79,216,20,0,140,0,153,246,7,
84592 128,35,0,35,0,36,253,130,96,8,192,8,192,9,159,96,176,2,152,2,167,216,52,0,
84593 166,0,169,246,39,2,162,2,163,125,138,64,168,128,166,191,98,176,42,32,41,
84594 223,216,180,10,156,10,141,246,47,2,162,2,158,128,
84595 };
84596 const duk_uint8_t duk_unicode_caseconv_lc[680] = {
84597 152,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
84598 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
84599 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
84600 240,19,248,12,62,16,62,0,32,124,96,124,64,48,249,64,249,0,129,243,129,243,
84601 1,3,233,3,232,1,135,218,7,216,4,15,196,15,192,8,31,152,31,144,16,63,80,63,
84602 64,32,126,224,126,192,16,253,208,251,128,33,252,129,247,32,131,251,3,250,0,
84603 135,246,135,221,129,15,244,15,240,2,31,234,31,122,4,63,240,62,240,8,127,
84604 232,125,240,17,11,1,11,129,2,75,98,77,3,69,128,5,134,11,203,31,128,143,193,
84605 127,144,255,160,154,140,4,0,4,4,192,9,144,9,152,48,19,144,19,161,0,41,64,
84606 41,101,192,94,64,94,129,128,193,0,193,130,1,160,1,161,6,3,102,3,104,8,7,44,
84607 7,48,72,14,240,14,248,144,31,32,31,48,64,63,0,63,37,0,136,128,136,196,129,
84608 35,1,35,133,3,112,3,113,4,7,176,7,178,48,17,128,17,132,136,36,80,36,89,176,
84609 76,16,76,32,224,154,0,154,44,7,128,7,128,101,143,80,15,80,176,31,89,31,81,
84610 8,88,206,88,208,12,178,0,178,5,145,103,89,103,96,42,100,10,100,18,244,208,
84611 20,208,35,169,200,169,200,195,211,153,83,153,159,167,121,167,122,5,78,253,
84612 78,254,22,158,66,158,68,21,60,181,60,184,170,123,74,123,80,67,0,211,1,64,2,
84613 1,172,1,173,4,3,136,3,140,12,7,20,7,24,16,31,184,31,192,34,199,34,199,48,
84614 65,128,195,128,196,2,1,184,1,185,5,79,84,4,204,8,0,192,101,128,154,65,1,29,
84615 129,30,2,16,199,45,39,5,251,240,23,128,15,240,24,16,37,48,24,96,37,64,24,
84616 224,29,208,24,240,37,144,25,0,37,176,25,16,25,32,25,48,38,0,25,64,38,48,25,
84617 112,38,128,25,128,25,144,25,208,39,32,25,240,39,80,26,112,26,128,26,224,40,
84618 128,27,112,41,32,31,16,31,48,31,96,25,80,31,112,27,240,34,0,25,224,35,162,
84619 198,80,35,208,25,160,35,226,198,96,36,48,24,0,36,64,40,144,36,80,40,192,55,
84620 96,55,112,55,240,63,48,56,96,58,192,56,192,60,192,60,240,61,112,63,64,59,
84621 128,63,144,63,32,76,0,76,241,233,224,13,241,251,193,251,49,252,193,252,49,
84622 254,193,254,81,255,193,255,50,18,96,60,146,18,160,6,178,18,176,14,82,19,34,
84623 20,226,24,50,24,66,198,2,198,18,198,32,38,178,198,49,215,210,198,64,39,210,
84624 198,208,37,18,198,224,39,18,198,240,37,2,199,0,37,34,207,34,207,58,119,209,
84625 215,154,120,186,120,202,120,208,38,90,122,176,37,202,122,192,38,26,122,208,
84626 38,202,123,0,41,234,123,16,40,122,123,32,41,218,123,58,181,48,32,38,16,3,
84627 72,24,56,
84628 };
84629 
84630 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
84631 /*
84632  * Automatically generated by extract_caseconv.py, do not edit!
84633  */
84634 
84635 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
84636 0,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,
84637 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,
84638 53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,
84639 78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,
84640 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
84641 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
84642 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
84643 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
84644 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
84645 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
84646 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
84647 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
84648 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
84649 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
84650 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
84651 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
84652 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
84653 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
84654 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
84655 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
84656 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
84657 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
84658 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
84659 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
84660 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
84661 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
84662 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
84663 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
84664 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
84665 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
84666 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
84667 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
84668 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
84669 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
84670 422,641,642,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,657,
84671 439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,674,
84672 675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,
84673 693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,
84674 711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,
84675 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,
84676 747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,
84677 765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,
84678 783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,
84679 801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,
84680 819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,
84681 921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,
84682 855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,
84683 873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,890,
84684 1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,
84685 909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,
84686 927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,944,
84687 913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,
84688 931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,980,
84689 934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,998,
84690 998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,1014,
84691 1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,
84692 1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,
84693 1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,
84694 1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,
84695 1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,
84696 1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,
84697 1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,
84698 1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,
84699 1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,
84700 1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,
84701 1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,
84702 1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,
84703 1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,
84704 1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,
84705 1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,
84706 1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,
84707 1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,
84708 1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,
84709 1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,
84710 1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,
84711 1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,1329,
84712 1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,
84713 1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,
84714 1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,
84715 1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,
84716 1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,
84717 1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,
84718 1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,
84719 1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,
84720 1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,
84721 1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,
84722 1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,
84723 1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,
84724 1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,
84725 1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,
84726 1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,
84727 1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,
84728 1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,
84729 1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,
84730 1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,
84731 1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,
84732 1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,
84733 1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,
84734 1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,
84735 1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,
84736 1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,
84737 1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,
84738 1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,
84739 1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,
84740 1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,
84741 1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,
84742 1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,
84743 1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,
84744 1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,
84745 1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,
84746 1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,
84747 1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,
84748 1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,
84749 1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,
84750 1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,
84751 1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,
84752 1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,
84753 1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,
84754 1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,
84755 1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,
84756 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
84757 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,
84758 2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,
84759 2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,
84760 2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,
84761 2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,
84762 2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,
84763 2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,
84764 2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,
84765 2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,
84766 2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,
84767 2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,
84768 2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,
84769 2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,
84770 2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,
84771 2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,
84772 2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,
84773 2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,
84774 2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,
84775 2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,
84776 2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,
84777 2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,
84778 2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,
84779 2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,
84780 2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,
84781 2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,
84782 2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,
84783 2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,
84784 2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,
84785 2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,
84786 2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,
84787 2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,
84788 2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,
84789 2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,
84790 2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,
84791 2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,
84792 2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,
84793 2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,
84794 2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,
84795 2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,
84796 2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,
84797 2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,
84798 2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,
84799 2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,
84800 2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,
84801 2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,
84802 2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,
84803 2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,
84804 2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,
84805 2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,
84806 2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,
84807 2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,
84808 2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,
84809 2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,
84810 2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,
84811 2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,
84812 2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,
84813 2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,
84814 2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,
84815 2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,
84816 2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,
84817 2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,
84818 2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,
84819 2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,
84820 2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,
84821 2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,
84822 2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,
84823 2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,
84824 3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,
84825 3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,
84826 3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,
84827 3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,
84828 3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,
84829 3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,
84830 3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,
84831 3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,
84832 3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,
84833 3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,
84834 3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,
84835 3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,
84836 3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,
84837 3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,
84838 3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,
84839 3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,
84840 3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,
84841 3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,
84842 3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,
84843 3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,
84844 3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,
84845 3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,
84846 3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,
84847 3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,
84848 3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,
84849 3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,
84850 3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,
84851 3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,
84852 3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,
84853 3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,
84854 3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,
84855 3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,
84856 3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,
84857 3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,
84858 3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,
84859 3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,
84860 3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,
84861 3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,
84862 3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,
84863 3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,
84864 3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,
84865 3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,
84866 3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,
84867 3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,
84868 3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,
84869 3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,
84870 3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,
84871 3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,
84872 3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,
84873 3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,
84874 3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,
84875 3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,
84876 3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,
84877 3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,
84878 3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,
84879 3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,
84880 3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,
84881 3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,
84882 3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,
84883 3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,
84884 3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,
84885 3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,
84886 3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,
84887 3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,
84888 3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,
84889 3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,
84890 4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,
84891 4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,
84892 4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,
84893 4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,
84894 4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,
84895 4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,
84896 4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,
84897 4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,
84898 4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,
84899 4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,
84900 4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,
84901 4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,
84902 4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,
84903 4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,
84904 4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,
84905 4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,
84906 4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,
84907 4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,
84908 4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,
84909 4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,
84910 4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,
84911 4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,
84912 4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,
84913 4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,
84914 4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,
84915 4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,
84916 4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,
84917 4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,
84918 4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,
84919 4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,
84920 4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,
84921 4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,
84922 4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,
84923 4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,
84924 4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,
84925 4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,
84926 4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,
84927 4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,
84928 4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,
84929 4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,
84930 4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,
84931 4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,
84932 4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,
84933 4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,
84934 4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,
84935 4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,
84936 4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,
84937 4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,
84938 4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,
84939 4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,
84940 4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,
84941 4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,
84942 4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,
84943 4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,
84944 4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,
84945 4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,
84946 4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,
84947 4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,
84948 4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,
84949 4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,
84950 4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,
84951 4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,
84952 4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,
84953 4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,
84954 4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,
84955 4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,
84956 4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,
84957 5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,
84958 5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,
84959 5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,
84960 5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,
84961 5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,
84962 5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,
84963 5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,
84964 5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,5124,
84965 5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,
84966 5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,
84967 5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,
84968 5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,
84969 5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,
84970 5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,
84971 5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,
84972 5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,
84973 5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,
84974 5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,
84975 5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,
84976 5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,
84977 5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,
84978 5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,
84979 5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,
84980 5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,
84981 5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,
84982 5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,
84983 5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,
84984 5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,
84985 5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,
84986 5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,
84987 5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,
84988 5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,
84989 5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,
84990 5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,
84991 5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,
84992 5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,
84993 5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,
84994 5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,
84995 5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,
84996 5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,
84997 5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,
84998 5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,
84999 5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,
85000 5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,
85001 5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,
85002 5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,
85003 5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,
85004 5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,
85005 5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,
85006 5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,
85007 5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,
85008 5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,
85009 5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,
85010 5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,
85011 5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,
85012 5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,
85013 5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,
85014 5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,
85015 5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,
85016 5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,
85017 5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,
85018 5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,
85019 5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,
85020 5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,
85021 5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,
85022 5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,
85023 5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
85024 6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,
85025 6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,
85026 6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,
85027 6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,
85028 6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,
85029 6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,
85030 6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,
85031 6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,
85032 6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,
85033 6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,
85034 6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,
85035 6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,
85036 6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,
85037 6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,
85038 6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,
85039 6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,
85040 6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,
85041 6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,
85042 6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,
85043 6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,
85044 6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,
85045 6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,
85046 6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,
85047 6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,
85048 6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,
85049 6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,
85050 6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,
85051 6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,
85052 6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,
85053 6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,
85054 6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,
85055 6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,
85056 6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,
85057 6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,
85058 6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,
85059 6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,
85060 6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,
85061 6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,
85062 6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,
85063 6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,
85064 6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,
85065 6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,
85066 6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,
85067 6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,
85068 6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,
85069 6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,
85070 6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,
85071 6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,
85072 6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,
85073 6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,
85074 6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,
85075 6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,
85076 6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,
85077 6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,
85078 6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,
85079 6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,
85080 6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,
85081 6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,
85082 6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,
85083 6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,
85084 6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,
85085 6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,
85086 6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,
85087 6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,
85088 6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,
85089 6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,
85090 7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,
85091 7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,
85092 7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,
85093 7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,
85094 7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,
85095 7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,
85096 7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,
85097 7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,
85098 7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,
85099 7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,
85100 7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,
85101 7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,
85102 7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,
85103 7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,
85104 7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,
85105 7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,
85106 7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,
85107 7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,
85108 7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,
85109 7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,1057,
85110 1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,7313,
85111 7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,
85112 7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,
85113 7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,
85114 7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,
85115 7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,
85116 7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,
85117 7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,
85118 7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,
85119 7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,
85120 7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,
85121 7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,
85122 7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,
85123 7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,
85124 7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,
85125 7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,
85126 7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,7552,
85127 7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,
85128 7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,
85129 7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,
85130 7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,
85131 7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,
85132 7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,
85133 7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,
85134 7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,
85135 7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,
85136 7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,
85137 7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,
85138 7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,
85139 7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,
85140 7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,
85141 7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,
85142 7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,
85143 7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,
85144 7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,
85145 7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,
85146 7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,
85147 7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,
85148 7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,
85149 7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,
85150 7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,
85151 7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,
85152 7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,
85153 7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,
85154 7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,
85155 7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,
85156 7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,
85157 8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,
85158 8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,
85159 8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,
85160 8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,
85161 8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,
85162 8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,
85163 8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,
85164 8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,
85165 8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,
85166 8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,
85167 8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,
85168 8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,
85169 8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,
85170 8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,
85171 8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,
85172 8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,
85173 8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,
85174 8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,
85175 8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,
85176 8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,
85177 8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,
85178 8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,
85179 8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,
85180 8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,
85181 8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,
85182 8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,
85183 8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,
85184 8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,
85185 8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,
85186 8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,
85187 8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,
85188 8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,
85189 8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,
85190 8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,
85191 8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,
85192 8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,
85193 8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,
85194 8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,
85195 8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,
85196 8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,
85197 8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,
85198 8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,
85199 8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,
85200 8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,
85201 8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,
85202 8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,
85203 8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,
85204 8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,
85205 8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,
85206 8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,
85207 8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,
85208 8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,
85209 8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,
85210 8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,
85211 8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,
85212 8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,
85213 8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,
85214 8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,
85215 8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,
85216 8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,
85217 8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,
85218 8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,
85219 8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,
85220 8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,
85221 8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,
85222 8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,
85223 8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,
85224 9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,
85225 9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,
85226 9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,
85227 9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,
85228 9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,
85229 9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,
85230 9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,
85231 9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,
85232 9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,
85233 9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,
85234 9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,
85235 9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,
85236 9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,
85237 9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,
85238 9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,
85239 9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,
85240 9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,
85241 9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,
85242 9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,
85243 9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,
85244 9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,
85245 9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,
85246 9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,
85247 9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,
85248 9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,
85249 9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,
85250 9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,
85251 9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,
85252 9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,
85253 9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,
85254 9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,
85255 9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,
85256 9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,
85257 9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,
85258 9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,
85259 9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,
85260 9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,
85261 9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,
85262 9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,
85263 9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,
85264 9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,
85265 9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,
85266 9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,
85267 9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,
85268 9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,
85269 9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,
85270 9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,
85271 9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,
85272 9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,
85273 9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,
85274 9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,
85275 9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,
85276 9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,
85277 9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,
85278 9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,
85279 9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,
85280 9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,
85281 9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,
85282 9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,
85283 9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,
85284 9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,
85285 9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,
85286 9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,
85287 9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,
85288 9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,
85289 9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,
85290 9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,
85291 10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,
85292 10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033,
85293 10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,
85294 10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,10056,10057,
85295 10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,10068,10069,
85296 10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080,10081,
85297 10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,10092,10093,
85298 10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,
85299 10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,
85300 10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,
85301 10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,10141,
85302 10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,10152,10153,
85303 10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,
85304 10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,
85305 10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,10188,10189,
85306 10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,10200,10201,
85307 10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,10212,10213,
85308 10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,
85309 10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,10236,10237,
85310 10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,10248,10249,
85311 10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,10260,10261,
85312 10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,
85313 10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,
85314 10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,
85315 10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,10308,10309,
85316 10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,10320,10321,
85317 10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,
85318 10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,10344,10345,
85319 10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,10356,10357,
85320 10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,10368,10369,
85321 10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,10380,10381,
85322 10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,10393,
85323 10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,
85324 10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,10416,10417,
85325 10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,10428,10429,
85326 10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,10440,10441,
85327 10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,10452,10453,
85328 10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,
85329 10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,
85330 10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,10488,10489,
85331 10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,10500,10501,
85332 10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,10512,10513,
85333 10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,10524,10525,
85334 10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,
85335 10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,10548,10549,
85336 10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,10560,10561,
85337 10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,
85338 10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,
85339 10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,
85340 10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,
85341 10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,
85342 10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,10632,10633,
85343 10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,
85344 10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,10656,10657,
85345 10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,10668,10669,
85346 10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,10680,10681,
85347 10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692,10693,
85348 10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,10704,10705,
85349 10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,10716,10717,
85350 10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,10728,10729,
85351 10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,10740,10741,
85352 10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,10752,10753,
85353 10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,10764,10765,
85354 10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,
85355 10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,10788,10789,
85356 10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,10800,10801,
85357 10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812,10813,
85358 10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,
85359 10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,10836,10837,
85360 10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,10848,10849,
85361 10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860,10861,
85362 10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,
85363 10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,10884,10885,
85364 10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,10896,10897,
85365 10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,10908,10909,
85366 10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,10920,10921,
85367 10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,10933,
85368 10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,10944,10945,
85369 10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,10956,10957,
85370 10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,10968,10969,
85371 10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,
85372 10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,
85373 10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005,
85374 11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,11016,11017,
85375 11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029,
85376 11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,11040,11041,
85377 11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,11052,11053,
85378 11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,11064,11065,
85379 11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,11076,11077,
85380 11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088,11089,
85381 11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,
85382 11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,11112,11113,
85383 11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,11124,11125,
85384 11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,11136,11137,
85385 11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,
85386 11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,
85387 11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,11172,11173,
85388 11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,
85389 11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,11196,11197,
85390 11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,
85391 11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,
85392 11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,
85393 11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,
85394 11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,
85395 11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,
85396 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
85397 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
85398 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
85399 11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,11268,11269,
85400 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
85401 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
85402 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
85403 11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,11364,570,574,
85404 11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,11377,11378,
85405 11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,11389,11390,
85406 11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,11400,11402,
85407 11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,11412,11414,
85408 11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,11424,11426,
85409 11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,11436,11438,
85410 11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,11448,11450,
85411 11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,11460,11462,
85412 11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,11472,11474,
85413 11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,11484,11486,
85414 11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,11497,11498,
85415 11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,11509,11510,
85416 11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,4257,4258,4259,
85417 4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,
85418 4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,
85419 4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,11564,4301,11566,
85420 11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,
85421 11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,
85422 11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,
85423 11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,
85424 11615,11616,11617,11618,11619,11620,11621,11622,11623,11624,11625,11626,
85425 11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638,
85426 11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,
85427 11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,
85428 11663,11664,11665,11666,11667,11668,11669,11670,11671,11672,11673,11674,
85429 11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685,11686,
85430 11687,11688,11689,11690,11691,11692,11693,11694,11695,11696,11697,11698,
85431 11699,11700,11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,
85432 11711,11712,11713,11714,11715,11716,11717,11718,11719,11720,11721,11722,
85433 11723,11724,11725,11726,11727,11728,11729,11730,11731,11732,11733,11734,
85434 11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,
85435 11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,
85436 11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,
85437 11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,
85438 11783,11784,11785,11786,11787,11788,11789,11790,11791,11792,11793,11794,
85439 11795,11796,11797,11798,11799,11800,11801,11802,11803,11804,11805,11806,
85440 11807,11808,11809,11810,11811,11812,11813,11814,11815,11816,11817,11818,
85441 11819,11820,11821,11822,11823,11824,11825,11826,11827,11828,11829,11830,
85442 11831,11832,11833,11834,11835,11836,11837,11838,11839,11840,11841,11842,
85443 11843,11844,11845,11846,11847,11848,11849,11850,11851,11852,11853,11854,
85444 11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866,
85445 11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,
85446 11879,11880,11881,11882,11883,11884,11885,11886,11887,11888,11889,11890,
85447 11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,
85448 11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913,11914,
85449 11915,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,
85450 11927,11928,11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,
85451 11939,11940,11941,11942,11943,11944,11945,11946,11947,11948,11949,11950,
85452 11951,11952,11953,11954,11955,11956,11957,11958,11959,11960,11961,11962,
85453 11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,
85454 11975,11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,
85455 11987,11988,11989,11990,11991,11992,11993,11994,11995,11996,11997,11998,
85456 11999,12000,12001,12002,12003,12004,12005,12006,12007,12008,12009,12010,
85457 12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021,12022,
85458 12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,
85459 12035,12036,12037,12038,12039,12040,12041,12042,12043,12044,12045,12046,
85460 12047,12048,12049,12050,12051,12052,12053,12054,12055,12056,12057,12058,
85461 12059,12060,12061,12062,12063,12064,12065,12066,12067,12068,12069,12070,
85462 12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,
85463 12083,12084,12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,
85464 12095,12096,12097,12098,12099,12100,12101,12102,12103,12104,12105,12106,
85465 12107,12108,12109,12110,12111,12112,12113,12114,12115,12116,12117,12118,
85466 12119,12120,12121,12122,12123,12124,12125,12126,12127,12128,12129,12130,
85467 12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,
85468 12143,12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,
85469 12155,12156,12157,12158,12159,12160,12161,12162,12163,12164,12165,12166,
85470 12167,12168,12169,12170,12171,12172,12173,12174,12175,12176,12177,12178,
85471 12179,12180,12181,12182,12183,12184,12185,12186,12187,12188,12189,12190,
85472 12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,
85473 12203,12204,12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,
85474 12215,12216,12217,12218,12219,12220,12221,12222,12223,12224,12225,12226,
85475 12227,12228,12229,12230,12231,12232,12233,12234,12235,12236,12237,12238,
85476 12239,12240,12241,12242,12243,12244,12245,12246,12247,12248,12249,12250,
85477 12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,
85478 12263,12264,12265,12266,12267,12268,12269,12270,12271,12272,12273,12274,
85479 12275,12276,12277,12278,12279,12280,12281,12282,12283,12284,12285,12286,
85480 12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12297,12298,
85481 12299,12300,12301,12302,12303,12304,12305,12306,12307,12308,12309,12310,
85482 12311,12312,12313,12314,12315,12316,12317,12318,12319,12320,12321,12322,
85483 12323,12324,12325,12326,12327,12328,12329,12330,12331,12332,12333,12334,
85484 12335,12336,12337,12338,12339,12340,12341,12342,12343,12344,12345,12346,
85485 12347,12348,12349,12350,12351,12352,12353,12354,12355,12356,12357,12358,
85486 12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,
85487 12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,
85488 12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,
85489 12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,
85490 12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,
85491 12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,
85492 12431,12432,12433,12434,12435,12436,12437,12438,12439,12440,12441,12442,
85493 12443,12444,12445,12446,12447,12448,12449,12450,12451,12452,12453,12454,
85494 12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,
85495 12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,
85496 12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,
85497 12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,
85498 12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,
85499 12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,
85500 12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,
85501 12539,12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,
85502 12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,
85503 12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,
85504 12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,
85505 12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,
85506 12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,
85507 12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,
85508 12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,
85509 12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,
85510 12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,
85511 12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,
85512 12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,
85513 12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,
85514 12695,12696,12697,12698,12699,12700,12701,12702,12703,12704,12705,12706,
85515 12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,
85516 12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,
85517 12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742,
85518 12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,
85519 12755,12756,12757,12758,12759,12760,12761,12762,12763,12764,12765,12766,
85520 12767,12768,12769,12770,12771,12772,12773,12774,12775,12776,12777,12778,
85521 12779,12780,12781,12782,12783,12784,12785,12786,12787,12788,12789,12790,
85522 12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,
85523 12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,
85524 12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,
85525 12827,12828,12829,12830,12831,12832,12833,12834,12835,12836,12837,12838,
85526 12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849,12850,
85527 12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,12862,
85528 12863,12864,12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,
85529 12875,12876,12877,12878,12879,12880,12881,12882,12883,12884,12885,12886,
85530 12887,12888,12889,12890,12891,12892,12893,12894,12895,12896,12897,12898,
85531 12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,
85532 12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,
85533 12923,12924,12925,12926,12927,12928,12929,12930,12931,12932,12933,12934,
85534 12935,12936,12937,12938,12939,12940,12941,12942,12943,12944,12945,12946,
85535 12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,12957,12958,
85536 12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,
85537 12971,12972,12973,12974,12975,12976,12977,12978,12979,12980,12981,12982,
85538 12983,12984,12985,12986,12987,12988,12989,12990,12991,12992,12993,12994,
85539 12995,12996,12997,12998,12999,13000,13001,13002,13003,13004,13005,13006,
85540 13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018,
85541 13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,13030,
85542 13031,13032,13033,13034,13035,13036,13037,13038,13039,13040,13041,13042,
85543 13043,13044,13045,13046,13047,13048,13049,13050,13051,13052,13053,13054,
85544 13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065,13066,
85545 13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,
85546 13079,13080,13081,13082,13083,13084,13085,13086,13087,13088,13089,13090,
85547 13091,13092,13093,13094,13095,13096,13097,13098,13099,13100,13101,13102,
85548 13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113,13114,
85549 13115,13116,13117,13118,13119,13120,13121,13122,13123,13124,13125,13126,
85550 13127,13128,13129,13130,13131,13132,13133,13134,13135,13136,13137,13138,
85551 13139,13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,
85552 13151,13152,13153,13154,13155,13156,13157,13158,13159,13160,13161,13162,
85553 13163,13164,13165,13166,13167,13168,13169,13170,13171,13172,13173,13174,
85554 13175,13176,13177,13178,13179,13180,13181,13182,13183,13184,13185,13186,
85555 13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,
85556 13199,13200,13201,13202,13203,13204,13205,13206,13207,13208,13209,13210,
85557 13211,13212,13213,13214,13215,13216,13217,13218,13219,13220,13221,13222,
85558 13223,13224,13225,13226,13227,13228,13229,13230,13231,13232,13233,13234,
85559 13235,13236,13237,13238,13239,13240,13241,13242,13243,13244,13245,13246,
85560 13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,
85561 13259,13260,13261,13262,13263,13264,13265,13266,13267,13268,13269,13270,
85562 13271,13272,13273,13274,13275,13276,13277,13278,13279,13280,13281,13282,
85563 13283,13284,13285,13286,13287,13288,13289,13290,13291,13292,13293,13294,
85564 13295,13296,13297,13298,13299,13300,13301,13302,13303,13304,13305,13306,
85565 13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,
85566 13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,
85567 13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,
85568 13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,
85569 13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,
85570 13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,
85571 13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,
85572 13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,
85573 13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,
85574 13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,
85575 13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,
85576 13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,
85577 13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,
85578 13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,
85579 13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,
85580 13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,
85581 13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,
85582 13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,
85583 13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,
85584 13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,
85585 13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,
85586 13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,
85587 13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,
85588 13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,
85589 13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,
85590 13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,
85591 13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,
85592 13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,
85593 13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,
85594 13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,
85595 13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,
85596 13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,
85597 13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,
85598 13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,
85599 13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,
85600 13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,
85601 13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,
85602 13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,
85603 13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,
85604 13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,
85605 13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,
85606 13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,
85607 13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,
85608 13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,
85609 13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,
85610 13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,
85611 13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,
85612 13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,
85613 13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,
85614 13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,
85615 13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,
85616 13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,
85617 13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,
85618 13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,
85619 13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,
85620 13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,
85621 13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,
85622 13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,
85623 14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,
85624 14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,
85625 14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,
85626 14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,
85627 14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,
85628 14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,
85629 14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,
85630 14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,
85631 14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,
85632 14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,
85633 14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,
85634 14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,
85635 14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,
85636 14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,
85637 14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,
85638 14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,
85639 14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,
85640 14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,
85641 14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,
85642 14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,
85643 14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,
85644 14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,
85645 14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,
85646 14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,
85647 14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,
85648 14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,
85649 14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,
85650 14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,
85651 14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,
85652 14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,
85653 14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,
85654 14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,
85655 14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,
85656 14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,
85657 14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,
85658 14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,
85659 14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,
85660 14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,
85661 14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,
85662 14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,
85663 14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,
85664 14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,
85665 14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,
85666 14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,
85667 14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,
85668 14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,
85669 14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,
85670 14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,
85671 14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,
85672 14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,
85673 14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,
85674 14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,
85675 14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,
85676 14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,
85677 14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,
85678 14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,
85679 14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,
85680 14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,
85681 14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,
85682 14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,
85683 14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,
85684 14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,
85685 14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,
85686 14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,
85687 14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,
85688 14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,
85689 14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,
85690 14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,
85691 14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,
85692 14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,
85693 14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,
85694 14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,
85695 14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,
85696 14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,
85697 14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,
85698 14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,
85699 14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,
85700 14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,
85701 14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,
85702 14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,
85703 14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,
85704 14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,
85705 14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,
85706 14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,
85707 15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,
85708 15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,
85709 15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,
85710 15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,
85711 15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,
85712 15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,
85713 15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,
85714 15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,
85715 15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,
85716 15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,
85717 15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,
85718 15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,
85719 15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,
85720 15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,
85721 15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,
85722 15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,
85723 15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,
85724 15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,
85725 15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,
85726 15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,
85727 15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,
85728 15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,
85729 15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,
85730 15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,
85731 15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,
85732 15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,
85733 15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,
85734 15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,
85735 15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,
85736 15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,
85737 15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,
85738 15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,
85739 15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,
85740 15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,
85741 15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,
85742 15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,
85743 15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,
85744 15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,
85745 15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,
85746 15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,
85747 15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,
85748 15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,
85749 15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,
85750 15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,
85751 15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,
85752 15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,
85753 15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,
85754 15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,
85755 15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,
85756 15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,
85757 15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,
85758 15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,
85759 15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,
85760 15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,
85761 15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,
85762 15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,
85763 15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,
85764 15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,
85765 15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,
85766 15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,
85767 15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,
85768 15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,
85769 15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,
85770 15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,
85771 15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,
85772 15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,
85773 15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,
85774 15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,
85775 15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,
85776 15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,
85777 15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,
85778 15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,
85779 15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,
85780 15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,
85781 15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,
85782 15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,
85783 15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,
85784 15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,
85785 15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,
85786 15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,
85787 15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,
85788 15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,
85789 15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,
85790 16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,
85791 16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,
85792 16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,
85793 16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,
85794 16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,
85795 16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,
85796 16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,
85797 16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,
85798 16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,
85799 16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,
85800 16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,
85801 16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,
85802 16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,
85803 16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,
85804 16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,
85805 16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,
85806 16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,
85807 16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,
85808 16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,
85809 16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,
85810 16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,
85811 16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,
85812 16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,
85813 16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,
85814 16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,
85815 16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,
85816 16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,
85817 16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,
85818 16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,
85819 16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,
85820 16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,
85821 16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,
85822 16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,
85823 16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,
85824 16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,
85825 16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,
85826 16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,
85827 16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,
85828 16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,
85829 16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,
85830 16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,
85831 16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,
85832 16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,
85833 16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,
85834 16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,
85835 16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,
85836 16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,
85837 16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,
85838 16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,
85839 16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,
85840 16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,
85841 16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,
85842 16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,
85843 16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,
85844 16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,
85845 16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,
85846 16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,
85847 16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,
85848 16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,
85849 16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,
85850 16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,
85851 16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,
85852 16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,
85853 16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,
85854 16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,
85855 16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,
85856 16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,
85857 16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,
85858 16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,
85859 16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,
85860 16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,
85861 16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,
85862 16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,
85863 16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,
85864 16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,
85865 16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,
85866 16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,
85867 16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,
85868 16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,
85869 16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,
85870 16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,
85871 16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,
85872 16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,
85873 17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,
85874 17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,
85875 17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,
85876 17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,
85877 17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,
85878 17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,
85879 17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,
85880 17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,
85881 17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,
85882 17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,
85883 17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,
85884 17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,
85885 17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,
85886 17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,
85887 17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,
85888 17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,
85889 17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,
85890 17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,
85891 17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,
85892 17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,
85893 17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,
85894 17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,
85895 17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,
85896 17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,
85897 17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,
85898 17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,
85899 17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,
85900 17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,
85901 17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,
85902 17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,
85903 17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,
85904 17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,
85905 17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,
85906 17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,
85907 17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,
85908 17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,
85909 17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,
85910 17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,
85911 17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,
85912 17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,
85913 17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,
85914 17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,
85915 17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,
85916 17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,
85917 17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,
85918 17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,
85919 17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,
85920 17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,
85921 17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,
85922 17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,
85923 17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,
85924 17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,
85925 17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,
85926 17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,
85927 17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,
85928 17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,
85929 17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,
85930 17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,
85931 17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,
85932 17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,
85933 17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,
85934 17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,
85935 17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,
85936 17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,
85937 17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,
85938 17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,
85939 17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,
85940 17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,
85941 17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,
85942 17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,
85943 17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,
85944 17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,
85945 17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,
85946 17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,
85947 17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,
85948 17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,
85949 17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,
85950 17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,
85951 17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,
85952 17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,
85953 17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,
85954 17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,
85955 17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,
85956 17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,
85957 18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,
85958 18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,
85959 18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,
85960 18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,
85961 18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,
85962 18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,
85963 18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,
85964 18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,
85965 18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,
85966 18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,
85967 18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,
85968 18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,
85969 18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,
85970 18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,
85971 18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,
85972 18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,
85973 18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,
85974 18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,
85975 18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,
85976 18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,
85977 18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,
85978 18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,
85979 18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,
85980 18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,
85981 18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,
85982 18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,
85983 18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,
85984 18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,
85985 18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,
85986 18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,
85987 18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,
85988 18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,
85989 18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,
85990 18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,
85991 18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,
85992 18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,
85993 18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,
85994 18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,
85995 18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,
85996 18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,
85997 18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,
85998 18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,
85999 18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,
86000 18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,
86001 18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,
86002 18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,
86003 18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,
86004 18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,
86005 18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,
86006 18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,
86007 18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,
86008 18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,
86009 18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,
86010 18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,
86011 18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,
86012 18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,
86013 18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,
86014 18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,
86015 18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,
86016 18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,
86017 18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,
86018 18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,
86019 18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,
86020 18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,
86021 18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,
86022 18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,
86023 18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,
86024 18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,
86025 18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,
86026 18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,
86027 18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,
86028 18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,
86029 18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,
86030 18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,
86031 18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,
86032 18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,
86033 18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,
86034 18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,
86035 18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,
86036 18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,
86037 18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,
86038 18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,
86039 18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,
86040 19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,
86041 19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,
86042 19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,
86043 19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,
86044 19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,
86045 19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,
86046 19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,
86047 19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,
86048 19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,
86049 19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,
86050 19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,
86051 19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,
86052 19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,
86053 19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,
86054 19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,
86055 19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,
86056 19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,
86057 19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,
86058 19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,
86059 19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,
86060 19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,
86061 19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,
86062 19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,
86063 19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,
86064 19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,
86065 19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,
86066 19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,
86067 19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,
86068 19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,
86069 19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,
86070 19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,
86071 19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,
86072 19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,
86073 19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,
86074 19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,
86075 19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,
86076 19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,
86077 19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,
86078 19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,
86079 19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,
86080 19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,
86081 19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,
86082 19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,
86083 19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,
86084 19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,
86085 19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,
86086 19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,
86087 19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,
86088 19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,
86089 19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,
86090 19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,
86091 19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,
86092 19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,
86093 19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,
86094 19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,
86095 19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,
86096 19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,
86097 19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,
86098 19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,
86099 19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,
86100 19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,
86101 19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,
86102 19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,
86103 19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,
86104 19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,
86105 19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,
86106 19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,
86107 19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,
86108 19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,
86109 19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,
86110 19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,
86111 19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,
86112 19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,
86113 19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19894,
86114 19895,19896,19897,19898,19899,19900,19901,19902,19903,19904,19905,19906,
86115 19907,19908,19909,19910,19911,19912,19913,19914,19915,19916,19917,19918,
86116 19919,19920,19921,19922,19923,19924,19925,19926,19927,19928,19929,19930,
86117 19931,19932,19933,19934,19935,19936,19937,19938,19939,19940,19941,19942,
86118 19943,19944,19945,19946,19947,19948,19949,19950,19951,19952,19953,19954,
86119 19955,19956,19957,19958,19959,19960,19961,19962,19963,19964,19965,19966,
86120 19967,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,
86121 19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,
86122 19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,
86123 20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,
86124 20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,
86125 20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,
86126 20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,
86127 20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,
86128 20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,
86129 20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,
86130 20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,
86131 20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,
86132 20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,
86133 20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,
86134 20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,
86135 20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,
86136 20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,
86137 20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,
86138 20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,
86139 20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,
86140 20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,
86141 20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,
86142 20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,
86143 20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,
86144 20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,
86145 20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,
86146 20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,
86147 20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,
86148 20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,
86149 20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,
86150 20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,
86151 20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,
86152 20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,
86153 20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,
86154 20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,
86155 20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,
86156 20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,
86157 20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,
86158 20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,
86159 20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,
86160 20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,
86161 20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,
86162 20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,
86163 20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,
86164 20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,
86165 20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,
86166 20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,
86167 20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,
86168 20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,
86169 20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,
86170 20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,
86171 20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,
86172 20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,
86173 20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,
86174 20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,
86175 20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,
86176 20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,
86177 20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,
86178 20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,
86179 20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,
86180 20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,
86181 20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,
86182 20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,
86183 20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,
86184 20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,
86185 20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,
86186 20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,
86187 20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,
86188 20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,
86189 20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,
86190 20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,
86191 20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,
86192 20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,
86193 20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,
86194 20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,
86195 20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,
86196 20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,
86197 20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,
86198 20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,
86199 20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,
86200 20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,
86201 20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,
86202 20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,
86203 20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,
86204 20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,
86205 20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,
86206 20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,
86207 21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,
86208 21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,
86209 21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,
86210 21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,
86211 21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,
86212 21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,
86213 21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,
86214 21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,
86215 21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,
86216 21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,
86217 21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,
86218 21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,
86219 21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,
86220 21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,
86221 21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,
86222 21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,
86223 21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,
86224 21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,
86225 21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,
86226 21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,
86227 21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,
86228 21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,
86229 21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,
86230 21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,
86231 21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,
86232 21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,
86233 21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,
86234 21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,
86235 21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,
86236 21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,
86237 21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,
86238 21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,
86239 21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,
86240 21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,
86241 21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,
86242 21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,
86243 21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,
86244 21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,
86245 21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,
86246 21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,
86247 21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,
86248 21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,
86249 21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,
86250 21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,
86251 21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,
86252 21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,
86253 21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,
86254 21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,
86255 21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,
86256 21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,
86257 21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,
86258 21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,
86259 21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,
86260 21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,
86261 21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,
86262 21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,
86263 21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,
86264 21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,
86265 21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,
86266 21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,
86267 21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,
86268 21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,
86269 21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,
86270 21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,
86271 21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,
86272 21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,
86273 21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,
86274 21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,
86275 21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,
86276 21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,
86277 21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,
86278 21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,
86279 21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,
86280 21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,
86281 21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,
86282 21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,
86283 21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,
86284 21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,
86285 21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,
86286 21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,
86287 21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,
86288 21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,
86289 21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,
86290 22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,
86291 22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,
86292 22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,
86293 22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,
86294 22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,
86295 22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,
86296 22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,
86297 22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,
86298 22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,
86299 22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,
86300 22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,
86301 22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,
86302 22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,
86303 22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,
86304 22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,
86305 22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,
86306 22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,
86307 22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,
86308 22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,
86309 22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,
86310 22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,
86311 22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,
86312 22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,
86313 22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,
86314 22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,
86315 22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,
86316 22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,
86317 22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,
86318 22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,
86319 22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,
86320 22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,
86321 22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,
86322 22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,
86323 22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,
86324 22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,
86325 22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,
86326 22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,
86327 22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,
86328 22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,
86329 22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,
86330 22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,
86331 22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,
86332 22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,
86333 22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,
86334 22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,
86335 22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,
86336 22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,
86337 22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,
86338 22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,
86339 22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,
86340 22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,
86341 22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,
86342 22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,
86343 22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,
86344 22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,
86345 22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,
86346 22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,
86347 22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,
86348 22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,
86349 22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,
86350 22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,
86351 22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,
86352 22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,
86353 22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,
86354 22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,
86355 22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,
86356 22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,
86357 22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,
86358 22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,
86359 22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,
86360 22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,
86361 22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,
86362 22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,
86363 22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,
86364 22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,
86365 22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,
86366 22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,
86367 22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,
86368 22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,
86369 22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,
86370 22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,
86371 22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,
86372 22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,
86373 23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,
86374 23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,
86375 23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,
86376 23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,
86377 23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,
86378 23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,
86379 23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,
86380 23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,
86381 23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,
86382 23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,
86383 23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,
86384 23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,
86385 23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,
86386 23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,
86387 23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,
86388 23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,
86389 23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,
86390 23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,
86391 23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,
86392 23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,
86393 23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,
86394 23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,
86395 23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,
86396 23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,
86397 23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,
86398 23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,
86399 23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,
86400 23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,
86401 23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,
86402 23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,
86403 23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,
86404 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,
86405 23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,
86406 23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,
86407 23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,
86408 23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,
86409 23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,
86410 23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,
86411 23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,
86412 23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,
86413 23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,
86414 23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,
86415 23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,
86416 23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,
86417 23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,
86418 23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,
86419 23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,
86420 23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,
86421 23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,
86422 23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,
86423 23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,
86424 23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,
86425 23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,
86426 23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,
86427 23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,
86428 23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,
86429 23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,
86430 23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,
86431 23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,
86432 23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,
86433 23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,
86434 23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,
86435 23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,
86436 23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,
86437 23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,
86438 23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,
86439 23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,
86440 23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,
86441 23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,
86442 23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,
86443 23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,
86444 23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,
86445 23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,
86446 23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,
86447 23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,
86448 23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,
86449 23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,
86450 23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,
86451 23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,
86452 23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,
86453 23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,
86454 23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,
86455 23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,
86456 23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,
86457 24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,
86458 24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,
86459 24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,
86460 24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,
86461 24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,
86462 24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,
86463 24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,
86464 24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,
86465 24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,
86466 24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,
86467 24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,
86468 24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,
86469 24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,
86470 24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,
86471 24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,
86472 24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,
86473 24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,
86474 24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,
86475 24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,
86476 24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,
86477 24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,
86478 24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,
86479 24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,
86480 24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,
86481 24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,
86482 24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,
86483 24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,
86484 24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,
86485 24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,
86486 24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,
86487 24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,
86488 24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,
86489 24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,
86490 24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,
86491 24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,
86492 24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,
86493 24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,
86494 24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,
86495 24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,
86496 24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,
86497 24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,
86498 24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,
86499 24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,
86500 24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,
86501 24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,
86502 24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,
86503 24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,
86504 24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,
86505 24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,
86506 24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,
86507 24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,
86508 24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,
86509 24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,
86510 24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,
86511 24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,
86512 24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,
86513 24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,
86514 24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,
86515 24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,
86516 24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,
86517 24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,
86518 24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,
86519 24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,
86520 24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,
86521 24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,
86522 24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,
86523 24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,
86524 24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,
86525 24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,
86526 24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,
86527 24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,
86528 24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,
86529 24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,
86530 24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,
86531 24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,
86532 24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,
86533 24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,
86534 24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,
86535 24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,
86536 24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,
86537 24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,
86538 24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,
86539 24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,
86540 25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,
86541 25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,
86542 25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,
86543 25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,
86544 25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,
86545 25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,
86546 25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,
86547 25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,
86548 25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,
86549 25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,
86550 25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,
86551 25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,
86552 25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,
86553 25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,
86554 25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,
86555 25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,
86556 25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,
86557 25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,
86558 25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,
86559 25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,
86560 25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,
86561 25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,
86562 25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,
86563 25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,
86564 25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,
86565 25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,
86566 25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,
86567 25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,
86568 25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,
86569 25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,
86570 25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,
86571 25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,
86572 25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,
86573 25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,
86574 25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,
86575 25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,
86576 25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,
86577 25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,
86578 25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,
86579 25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,
86580 25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,
86581 25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,
86582 25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,
86583 25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,
86584 25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,
86585 25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,
86586 25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,
86587 25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,
86588 25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,
86589 25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,
86590 25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,
86591 25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,
86592 25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,
86593 25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,
86594 25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,
86595 25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,
86596 25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,
86597 25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,
86598 25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,
86599 25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,
86600 25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,
86601 25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,
86602 25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,
86603 25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,
86604 25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,
86605 25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,
86606 25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,
86607 25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,
86608 25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,
86609 25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,
86610 25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,
86611 25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,
86612 25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,
86613 25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,
86614 25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,
86615 25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,
86616 25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,
86617 25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,
86618 25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,
86619 25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,
86620 25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,
86621 25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,
86622 25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,
86623 26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,
86624 26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,
86625 26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,
86626 26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,
86627 26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,
86628 26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,
86629 26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,
86630 26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,
86631 26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,
86632 26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,
86633 26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,
86634 26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,
86635 26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,
86636 26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,
86637 26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,
86638 26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,
86639 26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,
86640 26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,
86641 26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,
86642 26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,
86643 26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,
86644 26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,
86645 26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,
86646 26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,
86647 26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,
86648 26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,
86649 26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,
86650 26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,
86651 26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,
86652 26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,
86653 26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,
86654 26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,
86655 26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,
86656 26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,
86657 26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,
86658 26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,
86659 26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,
86660 26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,
86661 26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,
86662 26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,
86663 26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,
86664 26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,
86665 26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,
86666 26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,
86667 26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,
86668 26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,
86669 26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,
86670 26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,
86671 26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,
86672 26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,
86673 26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,
86674 26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,
86675 26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,
86676 26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,
86677 26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,
86678 26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,
86679 26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,
86680 26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,
86681 26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,
86682 26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,
86683 26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,
86684 26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,
86685 26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,
86686 26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,
86687 26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,
86688 26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,
86689 26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,
86690 26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,
86691 26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,
86692 26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,
86693 26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,
86694 26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,
86695 26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,
86696 26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,
86697 26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,
86698 26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,
86699 26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,
86700 26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,
86701 26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,
86702 26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,
86703 26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,
86704 26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,
86705 26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,
86706 26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,
86707 27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,
86708 27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,
86709 27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,
86710 27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,
86711 27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,
86712 27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,
86713 27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,
86714 27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,
86715 27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,
86716 27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,
86717 27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,
86718 27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,
86719 27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,
86720 27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,
86721 27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,
86722 27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,
86723 27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,
86724 27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,
86725 27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,
86726 27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,
86727 27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,
86728 27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,
86729 27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,
86730 27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,
86731 27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,
86732 27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,
86733 27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,
86734 27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,
86735 27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,
86736 27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,
86737 27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,
86738 27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,
86739 27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,
86740 27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,
86741 27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,
86742 27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,
86743 27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,
86744 27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,
86745 27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,
86746 27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,
86747 27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,
86748 27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,
86749 27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,
86750 27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,
86751 27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,
86752 27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,
86753 27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,
86754 27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,
86755 27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,
86756 27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,
86757 27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,
86758 27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,
86759 27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,
86760 27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,
86761 27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,
86762 27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,
86763 27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,
86764 27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,
86765 27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,
86766 27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,
86767 27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,
86768 27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,
86769 27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,
86770 27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,
86771 27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,
86772 27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,
86773 27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,
86774 27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,
86775 27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,
86776 27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,
86777 27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,
86778 27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,
86779 27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,
86780 27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,
86781 27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,
86782 27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,
86783 27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,
86784 27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,
86785 27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,
86786 27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,
86787 27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,
86788 27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,
86789 27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,
86790 28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,
86791 28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,
86792 28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,
86793 28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,
86794 28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,
86795 28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,
86796 28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,
86797 28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,
86798 28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,
86799 28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,
86800 28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,
86801 28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,
86802 28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,
86803 28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,
86804 28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,
86805 28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,
86806 28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,
86807 28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,
86808 28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,
86809 28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,
86810 28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,
86811 28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,
86812 28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,
86813 28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,
86814 28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,
86815 28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,
86816 28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,
86817 28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,
86818 28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,
86819 28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,
86820 28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,
86821 28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,
86822 28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,
86823 28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,
86824 28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,
86825 28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,
86826 28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,
86827 28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,
86828 28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,
86829 28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,
86830 28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,
86831 28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,
86832 28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,
86833 28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,
86834 28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,
86835 28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,
86836 28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,
86837 28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,
86838 28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,
86839 28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,
86840 28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,
86841 28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,
86842 28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,
86843 28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,
86844 28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,
86845 28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,
86846 28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,
86847 28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,
86848 28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,
86849 28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,
86850 28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,
86851 28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,
86852 28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,
86853 28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,
86854 28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,
86855 28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,
86856 28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,
86857 28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,
86858 28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,
86859 28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,
86860 28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,
86861 28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,
86862 28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,
86863 28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,
86864 28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,
86865 28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,
86866 28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,
86867 28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,
86868 28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,
86869 28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,
86870 28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,
86871 28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,
86872 28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,
86873 29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,
86874 29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,
86875 29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,
86876 29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,
86877 29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,
86878 29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,
86879 29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,
86880 29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,
86881 29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,
86882 29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,
86883 29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,
86884 29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,
86885 29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,
86886 29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,
86887 29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,
86888 29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,
86889 29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,
86890 29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,
86891 29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,
86892 29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,
86893 29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,
86894 29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,
86895 29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,
86896 29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,
86897 29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,
86898 29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,
86899 29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,
86900 29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,
86901 29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,
86902 29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,
86903 29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,
86904 29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,
86905 29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,
86906 29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,
86907 29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,
86908 29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,
86909 29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,
86910 29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,
86911 29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,
86912 29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,
86913 29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,
86914 29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,
86915 29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,
86916 29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,
86917 29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,
86918 29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,
86919 29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,
86920 29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,
86921 29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,
86922 29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,
86923 29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,
86924 29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,
86925 29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,
86926 29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,
86927 29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,
86928 29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,
86929 29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,
86930 29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,
86931 29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,
86932 29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,
86933 29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,
86934 29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,
86935 29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,
86936 29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,
86937 29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,
86938 29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,
86939 29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,
86940 29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,
86941 29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,
86942 29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,
86943 29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,
86944 29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,
86945 29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,
86946 29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,
86947 29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,
86948 29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,
86949 29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,
86950 29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,
86951 29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,
86952 29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,
86953 29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,
86954 29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,
86955 29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,
86956 29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,
86957 30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,
86958 30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,
86959 30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,
86960 30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,
86961 30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,
86962 30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,
86963 30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,
86964 30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,
86965 30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,
86966 30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,
86967 30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,
86968 30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,
86969 30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,
86970 30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,
86971 30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,
86972 30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,
86973 30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,
86974 30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,
86975 30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,
86976 30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,
86977 30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,
86978 30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,
86979 30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,
86980 30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,
86981 30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,
86982 30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,
86983 30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,
86984 30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,
86985 30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,
86986 30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,
86987 30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,
86988 30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,
86989 30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,
86990 30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,
86991 30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,
86992 30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,
86993 30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,
86994 30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,
86995 30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,
86996 30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,
86997 30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,
86998 30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,
86999 30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,
87000 30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,
87001 30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,
87002 30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,
87003 30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,
87004 30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,
87005 30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,
87006 30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,
87007 30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,
87008 30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,
87009 30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,
87010 30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,
87011 30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,
87012 30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,
87013 30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,
87014 30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,
87015 30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,
87016 30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,
87017 30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,
87018 30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,
87019 30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,
87020 30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,
87021 30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,
87022 30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,
87023 30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,
87024 30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,
87025 30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,
87026 30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,
87027 30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,
87028 30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,
87029 30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,
87030 30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,
87031 30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,
87032 30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,
87033 30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,
87034 30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,
87035 30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,
87036 30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,
87037 30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,
87038 30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,
87039 30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,
87040 31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,
87041 31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,
87042 31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,
87043 31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,
87044 31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,
87045 31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,
87046 31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,
87047 31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,
87048 31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,
87049 31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,
87050 31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,
87051 31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,
87052 31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,
87053 31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,
87054 31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,
87055 31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,
87056 31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,
87057 31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,
87058 31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,
87059 31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,
87060 31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,
87061 31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,
87062 31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,
87063 31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,
87064 31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,
87065 31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,
87066 31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,
87067 31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,
87068 31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,
87069 31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,
87070 31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,
87071 31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,
87072 31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,
87073 31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,
87074 31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,
87075 31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,
87076 31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,
87077 31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,
87078 31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,
87079 31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,
87080 31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,
87081 31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,
87082 31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,
87083 31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,
87084 31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,
87085 31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,
87086 31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,
87087 31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,
87088 31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,
87089 31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,
87090 31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,
87091 31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,
87092 31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,
87093 31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,
87094 31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,
87095 31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,
87096 31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,
87097 31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,
87098 31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,
87099 31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,
87100 31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,
87101 31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,
87102 31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,
87103 31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,
87104 31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,
87105 31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,
87106 31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,
87107 31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,
87108 31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,
87109 31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,
87110 31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,
87111 31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,
87112 31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,
87113 31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,
87114 31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,
87115 31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,
87116 31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,
87117 31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,
87118 31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,
87119 31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,
87120 31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,
87121 31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,
87122 31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,
87123 32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,
87124 32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,
87125 32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,
87126 32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,
87127 32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,
87128 32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,
87129 32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,
87130 32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,
87131 32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,
87132 32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,
87133 32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,
87134 32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,
87135 32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,
87136 32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,
87137 32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,
87138 32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,
87139 32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,
87140 32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,
87141 32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,
87142 32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,
87143 32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,
87144 32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,
87145 32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,
87146 32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,
87147 32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,
87148 32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,
87149 32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,
87150 32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,
87151 32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,
87152 32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,
87153 32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,
87154 32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,
87155 32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,
87156 32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,
87157 32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,
87158 32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,
87159 32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,
87160 32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,
87161 32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,
87162 32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,
87163 32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,
87164 32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,
87165 32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,
87166 32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,
87167 32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,
87168 32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,
87169 32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,
87170 32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,
87171 32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,
87172 32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,
87173 32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,
87174 32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,
87175 32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,
87176 32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,
87177 32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,
87178 32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,
87179 32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,
87180 32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,
87181 32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,
87182 32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,
87183 32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,
87184 32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,
87185 32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,
87186 32759,32760,32761,32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,
87187 32771L,32772L,32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,
87188 32781L,32782L,32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,
87189 32791L,32792L,32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,
87190 32801L,32802L,32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,
87191 32811L,32812L,32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,
87192 32821L,32822L,32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,
87193 32831L,32832L,32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,
87194 32841L,32842L,32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,
87195 32851L,32852L,32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,
87196 32861L,32862L,32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,
87197 32871L,32872L,32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,
87198 32881L,32882L,32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,
87199 32891L,32892L,32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,
87200 32901L,32902L,32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,
87201 32911L,32912L,32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,
87202 32921L,32922L,32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,
87203 32931L,32932L,32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,
87204 32941L,32942L,32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,
87205 32951L,32952L,32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,
87206 32961L,32962L,32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,
87207 32971L,32972L,32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,
87208 32981L,32982L,32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,
87209 32991L,32992L,32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,
87210 33001L,33002L,33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,
87211 33011L,33012L,33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,
87212 33021L,33022L,33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,
87213 33031L,33032L,33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,
87214 33041L,33042L,33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,
87215 33051L,33052L,33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,
87216 33061L,33062L,33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,
87217 33071L,33072L,33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,
87218 33081L,33082L,33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,
87219 33091L,33092L,33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,
87220 33101L,33102L,33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,
87221 33111L,33112L,33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,
87222 33121L,33122L,33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,
87223 33131L,33132L,33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,
87224 33141L,33142L,33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,
87225 33151L,33152L,33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,
87226 33161L,33162L,33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,
87227 33171L,33172L,33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,
87228 33181L,33182L,33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,
87229 33191L,33192L,33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,
87230 33201L,33202L,33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,
87231 33211L,33212L,33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,
87232 33221L,33222L,33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,
87233 33231L,33232L,33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,
87234 33241L,33242L,33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,
87235 33251L,33252L,33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,
87236 33261L,33262L,33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,
87237 33271L,33272L,33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,
87238 33281L,33282L,33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,
87239 33291L,33292L,33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,
87240 33301L,33302L,33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,
87241 33311L,33312L,33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,
87242 33321L,33322L,33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,
87243 33331L,33332L,33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,
87244 33341L,33342L,33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,
87245 33351L,33352L,33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,
87246 33361L,33362L,33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,
87247 33371L,33372L,33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,
87248 33381L,33382L,33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,
87249 33391L,33392L,33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,
87250 33401L,33402L,33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,
87251 33411L,33412L,33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,
87252 33421L,33422L,33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,
87253 33431L,33432L,33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,
87254 33441L,33442L,33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,
87255 33451L,33452L,33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,
87256 33461L,33462L,33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,
87257 33471L,33472L,33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,
87258 33481L,33482L,33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,
87259 33491L,33492L,33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,
87260 33501L,33502L,33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,
87261 33511L,33512L,33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,
87262 33521L,33522L,33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,
87263 33531L,33532L,33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,
87264 33541L,33542L,33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,
87265 33551L,33552L,33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,
87266 33561L,33562L,33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,
87267 33571L,33572L,33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,
87268 33581L,33582L,33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,
87269 33591L,33592L,33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,
87270 33601L,33602L,33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,
87271 33611L,33612L,33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,
87272 33621L,33622L,33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,
87273 33631L,33632L,33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,
87274 33641L,33642L,33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,
87275 33651L,33652L,33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,
87276 33661L,33662L,33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,
87277 33671L,33672L,33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,
87278 33681L,33682L,33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,
87279 33691L,33692L,33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,
87280 33701L,33702L,33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,
87281 33711L,33712L,33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,
87282 33721L,33722L,33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,
87283 33731L,33732L,33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,
87284 33741L,33742L,33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,
87285 33751L,33752L,33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,
87286 33761L,33762L,33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,
87287 33771L,33772L,33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,
87288 33781L,33782L,33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,
87289 33791L,33792L,33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,
87290 33801L,33802L,33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,
87291 33811L,33812L,33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,
87292 33821L,33822L,33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,
87293 33831L,33832L,33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,
87294 33841L,33842L,33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,
87295 33851L,33852L,33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,
87296 33861L,33862L,33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,
87297 33871L,33872L,33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,
87298 33881L,33882L,33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,
87299 33891L,33892L,33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,
87300 33901L,33902L,33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,
87301 33911L,33912L,33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,
87302 33921L,33922L,33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,
87303 33931L,33932L,33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,
87304 33941L,33942L,33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,
87305 33951L,33952L,33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,
87306 33961L,33962L,33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,
87307 33971L,33972L,33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,
87308 33981L,33982L,33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,
87309 33991L,33992L,33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,
87310 34001L,34002L,34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,
87311 34011L,34012L,34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,
87312 34021L,34022L,34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,
87313 34031L,34032L,34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,
87314 34041L,34042L,34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,
87315 34051L,34052L,34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,
87316 34061L,34062L,34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,
87317 34071L,34072L,34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,
87318 34081L,34082L,34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,
87319 34091L,34092L,34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,
87320 34101L,34102L,34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,
87321 34111L,34112L,34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,
87322 34121L,34122L,34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,
87323 34131L,34132L,34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,
87324 34141L,34142L,34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,
87325 34151L,34152L,34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,
87326 34161L,34162L,34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,
87327 34171L,34172L,34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,
87328 34181L,34182L,34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,
87329 34191L,34192L,34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,
87330 34201L,34202L,34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,
87331 34211L,34212L,34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,
87332 34221L,34222L,34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,
87333 34231L,34232L,34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,
87334 34241L,34242L,34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,
87335 34251L,34252L,34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,
87336 34261L,34262L,34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,
87337 34271L,34272L,34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,
87338 34281L,34282L,34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,
87339 34291L,34292L,34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,
87340 34301L,34302L,34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,
87341 34311L,34312L,34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,
87342 34321L,34322L,34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,
87343 34331L,34332L,34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,
87344 34341L,34342L,34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,
87345 34351L,34352L,34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,
87346 34361L,34362L,34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,
87347 34371L,34372L,34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,
87348 34381L,34382L,34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,
87349 34391L,34392L,34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,
87350 34401L,34402L,34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,
87351 34411L,34412L,34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,
87352 34421L,34422L,34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,
87353 34431L,34432L,34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,
87354 34441L,34442L,34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,
87355 34451L,34452L,34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,
87356 34461L,34462L,34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,
87357 34471L,34472L,34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,
87358 34481L,34482L,34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,
87359 34491L,34492L,34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,
87360 34501L,34502L,34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,
87361 34511L,34512L,34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,
87362 34521L,34522L,34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,
87363 34531L,34532L,34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,
87364 34541L,34542L,34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,
87365 34551L,34552L,34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,
87366 34561L,34562L,34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,
87367 34571L,34572L,34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,
87368 34581L,34582L,34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,
87369 34591L,34592L,34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,
87370 34601L,34602L,34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,
87371 34611L,34612L,34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,
87372 34621L,34622L,34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,
87373 34631L,34632L,34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,
87374 34641L,34642L,34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,
87375 34651L,34652L,34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,
87376 34661L,34662L,34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,
87377 34671L,34672L,34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,
87378 34681L,34682L,34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,
87379 34691L,34692L,34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,
87380 34701L,34702L,34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,
87381 34711L,34712L,34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,
87382 34721L,34722L,34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,
87383 34731L,34732L,34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,
87384 34741L,34742L,34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,
87385 34751L,34752L,34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,
87386 34761L,34762L,34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,
87387 34771L,34772L,34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,
87388 34781L,34782L,34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,
87389 34791L,34792L,34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,
87390 34801L,34802L,34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,
87391 34811L,34812L,34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,
87392 34821L,34822L,34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,
87393 34831L,34832L,34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,
87394 34841L,34842L,34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,
87395 34851L,34852L,34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,
87396 34861L,34862L,34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,
87397 34871L,34872L,34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,
87398 34881L,34882L,34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,
87399 34891L,34892L,34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,
87400 34901L,34902L,34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,
87401 34911L,34912L,34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,
87402 34921L,34922L,34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,
87403 34931L,34932L,34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,
87404 34941L,34942L,34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,
87405 34951L,34952L,34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,
87406 34961L,34962L,34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,
87407 34971L,34972L,34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,
87408 34981L,34982L,34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,
87409 34991L,34992L,34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,
87410 35001L,35002L,35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,
87411 35011L,35012L,35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,
87412 35021L,35022L,35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,
87413 35031L,35032L,35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,
87414 35041L,35042L,35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,
87415 35051L,35052L,35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,
87416 35061L,35062L,35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,
87417 35071L,35072L,35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,
87418 35081L,35082L,35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,
87419 35091L,35092L,35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,
87420 35101L,35102L,35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,
87421 35111L,35112L,35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,
87422 35121L,35122L,35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,
87423 35131L,35132L,35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,
87424 35141L,35142L,35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,
87425 35151L,35152L,35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,
87426 35161L,35162L,35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,
87427 35171L,35172L,35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,
87428 35181L,35182L,35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,
87429 35191L,35192L,35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,
87430 35201L,35202L,35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,
87431 35211L,35212L,35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,
87432 35221L,35222L,35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,
87433 35231L,35232L,35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,
87434 35241L,35242L,35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,
87435 35251L,35252L,35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,
87436 35261L,35262L,35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,
87437 35271L,35272L,35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,
87438 35281L,35282L,35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,
87439 35291L,35292L,35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,
87440 35301L,35302L,35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,
87441 35311L,35312L,35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,
87442 35321L,35322L,35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,
87443 35331L,35332L,35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,
87444 35341L,35342L,35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,
87445 35351L,35352L,35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,
87446 35361L,35362L,35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,
87447 35371L,35372L,35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,
87448 35381L,35382L,35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,
87449 35391L,35392L,35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,
87450 35401L,35402L,35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,
87451 35411L,35412L,35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,
87452 35421L,35422L,35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,
87453 35431L,35432L,35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,
87454 35441L,35442L,35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,
87455 35451L,35452L,35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,
87456 35461L,35462L,35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,
87457 35471L,35472L,35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,
87458 35481L,35482L,35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,
87459 35491L,35492L,35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,
87460 35501L,35502L,35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,
87461 35511L,35512L,35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,
87462 35521L,35522L,35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,
87463 35531L,35532L,35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,
87464 35541L,35542L,35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,
87465 35551L,35552L,35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,
87466 35561L,35562L,35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,
87467 35571L,35572L,35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,
87468 35581L,35582L,35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,
87469 35591L,35592L,35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,
87470 35601L,35602L,35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,
87471 35611L,35612L,35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,
87472 35621L,35622L,35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,
87473 35631L,35632L,35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,
87474 35641L,35642L,35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,
87475 35651L,35652L,35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,
87476 35661L,35662L,35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,
87477 35671L,35672L,35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,
87478 35681L,35682L,35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,
87479 35691L,35692L,35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,
87480 35701L,35702L,35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,
87481 35711L,35712L,35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,
87482 35721L,35722L,35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,
87483 35731L,35732L,35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,
87484 35741L,35742L,35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,
87485 35751L,35752L,35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,
87486 35761L,35762L,35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,
87487 35771L,35772L,35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,
87488 35781L,35782L,35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,
87489 35791L,35792L,35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,
87490 35801L,35802L,35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,
87491 35811L,35812L,35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,
87492 35821L,35822L,35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,
87493 35831L,35832L,35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,
87494 35841L,35842L,35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,
87495 35851L,35852L,35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,
87496 35861L,35862L,35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,
87497 35871L,35872L,35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,
87498 35881L,35882L,35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,
87499 35891L,35892L,35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,
87500 35901L,35902L,35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,
87501 35911L,35912L,35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,
87502 35921L,35922L,35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,
87503 35931L,35932L,35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,
87504 35941L,35942L,35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,
87505 35951L,35952L,35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,
87506 35961L,35962L,35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,
87507 35971L,35972L,35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,
87508 35981L,35982L,35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,
87509 35991L,35992L,35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,
87510 36001L,36002L,36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,
87511 36011L,36012L,36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,
87512 36021L,36022L,36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,
87513 36031L,36032L,36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,
87514 36041L,36042L,36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,
87515 36051L,36052L,36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,
87516 36061L,36062L,36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,
87517 36071L,36072L,36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,
87518 36081L,36082L,36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,
87519 36091L,36092L,36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,
87520 36101L,36102L,36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,
87521 36111L,36112L,36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,
87522 36121L,36122L,36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,
87523 36131L,36132L,36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,
87524 36141L,36142L,36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,
87525 36151L,36152L,36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,
87526 36161L,36162L,36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,
87527 36171L,36172L,36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,
87528 36181L,36182L,36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,
87529 36191L,36192L,36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,
87530 36201L,36202L,36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,
87531 36211L,36212L,36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,
87532 36221L,36222L,36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,
87533 36231L,36232L,36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,
87534 36241L,36242L,36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,
87535 36251L,36252L,36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,
87536 36261L,36262L,36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,
87537 36271L,36272L,36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,
87538 36281L,36282L,36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,
87539 36291L,36292L,36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,
87540 36301L,36302L,36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,
87541 36311L,36312L,36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,
87542 36321L,36322L,36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,
87543 36331L,36332L,36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,
87544 36341L,36342L,36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,
87545 36351L,36352L,36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,
87546 36361L,36362L,36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,
87547 36371L,36372L,36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,
87548 36381L,36382L,36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,
87549 36391L,36392L,36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,
87550 36401L,36402L,36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,
87551 36411L,36412L,36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,
87552 36421L,36422L,36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,
87553 36431L,36432L,36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,
87554 36441L,36442L,36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,
87555 36451L,36452L,36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,
87556 36461L,36462L,36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,
87557 36471L,36472L,36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,
87558 36481L,36482L,36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,
87559 36491L,36492L,36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,
87560 36501L,36502L,36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,
87561 36511L,36512L,36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,
87562 36521L,36522L,36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,
87563 36531L,36532L,36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,
87564 36541L,36542L,36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,
87565 36551L,36552L,36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,
87566 36561L,36562L,36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,
87567 36571L,36572L,36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,
87568 36581L,36582L,36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,
87569 36591L,36592L,36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,
87570 36601L,36602L,36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,
87571 36611L,36612L,36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,
87572 36621L,36622L,36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,
87573 36631L,36632L,36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,
87574 36641L,36642L,36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,
87575 36651L,36652L,36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,
87576 36661L,36662L,36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,
87577 36671L,36672L,36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,
87578 36681L,36682L,36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,
87579 36691L,36692L,36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,
87580 36701L,36702L,36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,
87581 36711L,36712L,36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,
87582 36721L,36722L,36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,
87583 36731L,36732L,36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,
87584 36741L,36742L,36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,
87585 36751L,36752L,36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,
87586 36761L,36762L,36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,
87587 36771L,36772L,36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,
87588 36781L,36782L,36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,
87589 36791L,36792L,36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,
87590 36801L,36802L,36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,
87591 36811L,36812L,36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,
87592 36821L,36822L,36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,
87593 36831L,36832L,36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,
87594 36841L,36842L,36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,
87595 36851L,36852L,36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,
87596 36861L,36862L,36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,
87597 36871L,36872L,36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,
87598 36881L,36882L,36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,
87599 36891L,36892L,36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,
87600 36901L,36902L,36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,
87601 36911L,36912L,36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,
87602 36921L,36922L,36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,
87603 36931L,36932L,36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,
87604 36941L,36942L,36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,
87605 36951L,36952L,36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,
87606 36961L,36962L,36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,
87607 36971L,36972L,36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,
87608 36981L,36982L,36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,
87609 36991L,36992L,36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,
87610 37001L,37002L,37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,
87611 37011L,37012L,37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,
87612 37021L,37022L,37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,
87613 37031L,37032L,37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,
87614 37041L,37042L,37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,
87615 37051L,37052L,37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,
87616 37061L,37062L,37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,
87617 37071L,37072L,37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,
87618 37081L,37082L,37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,
87619 37091L,37092L,37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,
87620 37101L,37102L,37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,
87621 37111L,37112L,37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,
87622 37121L,37122L,37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,
87623 37131L,37132L,37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,
87624 37141L,37142L,37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,
87625 37151L,37152L,37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,
87626 37161L,37162L,37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,
87627 37171L,37172L,37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,
87628 37181L,37182L,37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,
87629 37191L,37192L,37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,
87630 37201L,37202L,37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,
87631 37211L,37212L,37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,
87632 37221L,37222L,37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,
87633 37231L,37232L,37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,
87634 37241L,37242L,37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,
87635 37251L,37252L,37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,
87636 37261L,37262L,37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,
87637 37271L,37272L,37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,
87638 37281L,37282L,37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,
87639 37291L,37292L,37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,
87640 37301L,37302L,37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,
87641 37311L,37312L,37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,
87642 37321L,37322L,37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,
87643 37331L,37332L,37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,
87644 37341L,37342L,37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,
87645 37351L,37352L,37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,
87646 37361L,37362L,37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,
87647 37371L,37372L,37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,
87648 37381L,37382L,37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,
87649 37391L,37392L,37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,
87650 37401L,37402L,37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,
87651 37411L,37412L,37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,
87652 37421L,37422L,37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,
87653 37431L,37432L,37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,
87654 37441L,37442L,37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,
87655 37451L,37452L,37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,
87656 37461L,37462L,37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,
87657 37471L,37472L,37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,
87658 37481L,37482L,37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,
87659 37491L,37492L,37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,
87660 37501L,37502L,37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,
87661 37511L,37512L,37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,
87662 37521L,37522L,37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,
87663 37531L,37532L,37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,
87664 37541L,37542L,37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,
87665 37551L,37552L,37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,
87666 37561L,37562L,37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,
87667 37571L,37572L,37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,
87668 37581L,37582L,37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,
87669 37591L,37592L,37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,
87670 37601L,37602L,37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,
87671 37611L,37612L,37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,
87672 37621L,37622L,37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,
87673 37631L,37632L,37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,
87674 37641L,37642L,37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,
87675 37651L,37652L,37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,
87676 37661L,37662L,37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,
87677 37671L,37672L,37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,
87678 37681L,37682L,37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,
87679 37691L,37692L,37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,
87680 37701L,37702L,37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,
87681 37711L,37712L,37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,
87682 37721L,37722L,37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,
87683 37731L,37732L,37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,
87684 37741L,37742L,37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,
87685 37751L,37752L,37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,
87686 37761L,37762L,37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,
87687 37771L,37772L,37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,
87688 37781L,37782L,37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,
87689 37791L,37792L,37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,
87690 37801L,37802L,37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,
87691 37811L,37812L,37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,
87692 37821L,37822L,37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,
87693 37831L,37832L,37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,
87694 37841L,37842L,37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,
87695 37851L,37852L,37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,
87696 37861L,37862L,37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,
87697 37871L,37872L,37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,
87698 37881L,37882L,37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,
87699 37891L,37892L,37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,
87700 37901L,37902L,37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,
87701 37911L,37912L,37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,
87702 37921L,37922L,37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,
87703 37931L,37932L,37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,
87704 37941L,37942L,37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,
87705 37951L,37952L,37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,
87706 37961L,37962L,37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,
87707 37971L,37972L,37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,
87708 37981L,37982L,37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,
87709 37991L,37992L,37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,
87710 38001L,38002L,38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,
87711 38011L,38012L,38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,
87712 38021L,38022L,38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,
87713 38031L,38032L,38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,
87714 38041L,38042L,38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,
87715 38051L,38052L,38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,
87716 38061L,38062L,38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,
87717 38071L,38072L,38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,
87718 38081L,38082L,38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,
87719 38091L,38092L,38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,
87720 38101L,38102L,38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,
87721 38111L,38112L,38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,
87722 38121L,38122L,38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,
87723 38131L,38132L,38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,
87724 38141L,38142L,38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,
87725 38151L,38152L,38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,
87726 38161L,38162L,38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,
87727 38171L,38172L,38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,
87728 38181L,38182L,38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,
87729 38191L,38192L,38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,
87730 38201L,38202L,38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,
87731 38211L,38212L,38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,
87732 38221L,38222L,38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,
87733 38231L,38232L,38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,
87734 38241L,38242L,38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,
87735 38251L,38252L,38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,
87736 38261L,38262L,38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,
87737 38271L,38272L,38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,
87738 38281L,38282L,38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,
87739 38291L,38292L,38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,
87740 38301L,38302L,38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,
87741 38311L,38312L,38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,
87742 38321L,38322L,38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,
87743 38331L,38332L,38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,
87744 38341L,38342L,38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,
87745 38351L,38352L,38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,
87746 38361L,38362L,38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,
87747 38371L,38372L,38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,
87748 38381L,38382L,38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,
87749 38391L,38392L,38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,
87750 38401L,38402L,38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,
87751 38411L,38412L,38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,
87752 38421L,38422L,38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,
87753 38431L,38432L,38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,
87754 38441L,38442L,38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,
87755 38451L,38452L,38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,
87756 38461L,38462L,38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,
87757 38471L,38472L,38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,
87758 38481L,38482L,38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,
87759 38491L,38492L,38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,
87760 38501L,38502L,38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,
87761 38511L,38512L,38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,
87762 38521L,38522L,38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,
87763 38531L,38532L,38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,
87764 38541L,38542L,38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,
87765 38551L,38552L,38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,
87766 38561L,38562L,38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,
87767 38571L,38572L,38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,
87768 38581L,38582L,38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,
87769 38591L,38592L,38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,
87770 38601L,38602L,38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,
87771 38611L,38612L,38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,
87772 38621L,38622L,38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,
87773 38631L,38632L,38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,
87774 38641L,38642L,38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,
87775 38651L,38652L,38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,
87776 38661L,38662L,38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,
87777 38671L,38672L,38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,
87778 38681L,38682L,38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,
87779 38691L,38692L,38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,
87780 38701L,38702L,38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,
87781 38711L,38712L,38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,
87782 38721L,38722L,38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,
87783 38731L,38732L,38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,
87784 38741L,38742L,38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,
87785 38751L,38752L,38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,
87786 38761L,38762L,38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,
87787 38771L,38772L,38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,
87788 38781L,38782L,38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,
87789 38791L,38792L,38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,
87790 38801L,38802L,38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,
87791 38811L,38812L,38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,
87792 38821L,38822L,38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,
87793 38831L,38832L,38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,
87794 38841L,38842L,38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,
87795 38851L,38852L,38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,
87796 38861L,38862L,38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,
87797 38871L,38872L,38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,
87798 38881L,38882L,38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,
87799 38891L,38892L,38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,
87800 38901L,38902L,38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,
87801 38911L,38912L,38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,
87802 38921L,38922L,38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,
87803 38931L,38932L,38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,
87804 38941L,38942L,38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,
87805 38951L,38952L,38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,
87806 38961L,38962L,38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,
87807 38971L,38972L,38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,
87808 38981L,38982L,38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,
87809 38991L,38992L,38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,
87810 39001L,39002L,39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,
87811 39011L,39012L,39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,
87812 39021L,39022L,39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,
87813 39031L,39032L,39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,
87814 39041L,39042L,39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,
87815 39051L,39052L,39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,
87816 39061L,39062L,39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,
87817 39071L,39072L,39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,
87818 39081L,39082L,39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,
87819 39091L,39092L,39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,
87820 39101L,39102L,39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,
87821 39111L,39112L,39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,
87822 39121L,39122L,39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,
87823 39131L,39132L,39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,
87824 39141L,39142L,39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,
87825 39151L,39152L,39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,
87826 39161L,39162L,39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,
87827 39171L,39172L,39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,
87828 39181L,39182L,39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,
87829 39191L,39192L,39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,
87830 39201L,39202L,39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,
87831 39211L,39212L,39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,
87832 39221L,39222L,39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,
87833 39231L,39232L,39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,
87834 39241L,39242L,39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,
87835 39251L,39252L,39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,
87836 39261L,39262L,39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,
87837 39271L,39272L,39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,
87838 39281L,39282L,39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,
87839 39291L,39292L,39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,
87840 39301L,39302L,39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,
87841 39311L,39312L,39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,
87842 39321L,39322L,39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,
87843 39331L,39332L,39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,
87844 39341L,39342L,39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,
87845 39351L,39352L,39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,
87846 39361L,39362L,39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,
87847 39371L,39372L,39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,
87848 39381L,39382L,39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,
87849 39391L,39392L,39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,
87850 39401L,39402L,39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,
87851 39411L,39412L,39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,
87852 39421L,39422L,39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,
87853 39431L,39432L,39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,
87854 39441L,39442L,39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,
87855 39451L,39452L,39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,
87856 39461L,39462L,39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,
87857 39471L,39472L,39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,
87858 39481L,39482L,39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,
87859 39491L,39492L,39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,
87860 39501L,39502L,39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,
87861 39511L,39512L,39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,
87862 39521L,39522L,39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,
87863 39531L,39532L,39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,
87864 39541L,39542L,39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,
87865 39551L,39552L,39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,
87866 39561L,39562L,39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,
87867 39571L,39572L,39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,
87868 39581L,39582L,39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,
87869 39591L,39592L,39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,
87870 39601L,39602L,39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,
87871 39611L,39612L,39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,
87872 39621L,39622L,39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,
87873 39631L,39632L,39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,
87874 39641L,39642L,39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,
87875 39651L,39652L,39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,
87876 39661L,39662L,39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,
87877 39671L,39672L,39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,
87878 39681L,39682L,39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,
87879 39691L,39692L,39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,
87880 39701L,39702L,39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,
87881 39711L,39712L,39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,
87882 39721L,39722L,39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,
87883 39731L,39732L,39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,
87884 39741L,39742L,39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,
87885 39751L,39752L,39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,
87886 39761L,39762L,39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,
87887 39771L,39772L,39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,
87888 39781L,39782L,39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,
87889 39791L,39792L,39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,
87890 39801L,39802L,39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,
87891 39811L,39812L,39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,
87892 39821L,39822L,39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,
87893 39831L,39832L,39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,
87894 39841L,39842L,39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,
87895 39851L,39852L,39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,
87896 39861L,39862L,39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,
87897 39871L,39872L,39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,
87898 39881L,39882L,39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,
87899 39891L,39892L,39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,
87900 39901L,39902L,39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,
87901 39911L,39912L,39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,
87902 39921L,39922L,39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,
87903 39931L,39932L,39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,
87904 39941L,39942L,39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,
87905 39951L,39952L,39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,
87906 39961L,39962L,39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,
87907 39971L,39972L,39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,
87908 39981L,39982L,39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,
87909 39991L,39992L,39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,
87910 40001L,40002L,40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,
87911 40011L,40012L,40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,
87912 40021L,40022L,40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,
87913 40031L,40032L,40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,
87914 40041L,40042L,40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,
87915 40051L,40052L,40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,
87916 40061L,40062L,40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,
87917 40071L,40072L,40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,
87918 40081L,40082L,40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,
87919 40091L,40092L,40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,
87920 40101L,40102L,40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,
87921 40111L,40112L,40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,
87922 40121L,40122L,40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,
87923 40131L,40132L,40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,
87924 40141L,40142L,40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,
87925 40151L,40152L,40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,
87926 40161L,40162L,40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,
87927 40171L,40172L,40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,
87928 40181L,40182L,40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,
87929 40191L,40192L,40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,
87930 40201L,40202L,40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,
87931 40211L,40212L,40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,
87932 40221L,40222L,40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,
87933 40231L,40232L,40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,
87934 40241L,40242L,40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,
87935 40251L,40252L,40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,
87936 40261L,40262L,40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,
87937 40271L,40272L,40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,
87938 40281L,40282L,40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,
87939 40291L,40292L,40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,
87940 40301L,40302L,40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,
87941 40311L,40312L,40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,
87942 40321L,40322L,40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,
87943 40331L,40332L,40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,
87944 40341L,40342L,40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,
87945 40351L,40352L,40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,
87946 40361L,40362L,40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,
87947 40371L,40372L,40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,
87948 40381L,40382L,40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,
87949 40391L,40392L,40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,
87950 40401L,40402L,40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,
87951 40411L,40412L,40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,
87952 40421L,40422L,40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,
87953 40431L,40432L,40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,
87954 40441L,40442L,40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,
87955 40451L,40452L,40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,
87956 40461L,40462L,40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,
87957 40471L,40472L,40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,
87958 40481L,40482L,40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,
87959 40491L,40492L,40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,
87960 40501L,40502L,40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,
87961 40511L,40512L,40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,
87962 40521L,40522L,40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,
87963 40531L,40532L,40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,
87964 40541L,40542L,40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,
87965 40551L,40552L,40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,
87966 40561L,40562L,40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,
87967 40571L,40572L,40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,
87968 40581L,40582L,40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,
87969 40591L,40592L,40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,
87970 40601L,40602L,40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,
87971 40611L,40612L,40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,
87972 40621L,40622L,40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,
87973 40631L,40632L,40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,
87974 40641L,40642L,40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,
87975 40651L,40652L,40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,
87976 40661L,40662L,40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,
87977 40671L,40672L,40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,
87978 40681L,40682L,40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,
87979 40691L,40692L,40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,
87980 40701L,40702L,40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,
87981 40711L,40712L,40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,
87982 40721L,40722L,40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,
87983 40731L,40732L,40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,
87984 40741L,40742L,40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,
87985 40751L,40752L,40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,
87986 40761L,40762L,40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,
87987 40771L,40772L,40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,
87988 40781L,40782L,40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,
87989 40791L,40792L,40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,
87990 40801L,40802L,40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,
87991 40811L,40812L,40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,
87992 40821L,40822L,40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,
87993 40831L,40832L,40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,
87994 40841L,40842L,40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,
87995 40851L,40852L,40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,
87996 40861L,40862L,40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,
87997 40871L,40872L,40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,
87998 40881L,40882L,40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,
87999 40891L,40892L,40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,
88000 40901L,40902L,40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,
88001 40911L,40912L,40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,
88002 40921L,40922L,40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,
88003 40931L,40932L,40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,
88004 40941L,40942L,40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,
88005 40951L,40952L,40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,
88006 40961L,40962L,40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,
88007 40971L,40972L,40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,
88008 40981L,40982L,40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,
88009 40991L,40992L,40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,
88010 41001L,41002L,41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,
88011 41011L,41012L,41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,
88012 41021L,41022L,41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,
88013 41031L,41032L,41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,
88014 41041L,41042L,41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,
88015 41051L,41052L,41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,
88016 41061L,41062L,41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,
88017 41071L,41072L,41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,
88018 41081L,41082L,41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,
88019 41091L,41092L,41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,
88020 41101L,41102L,41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,
88021 41111L,41112L,41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,
88022 41121L,41122L,41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,
88023 41131L,41132L,41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,
88024 41141L,41142L,41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,
88025 41151L,41152L,41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,
88026 41161L,41162L,41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,
88027 41171L,41172L,41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,
88028 41181L,41182L,41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,
88029 41191L,41192L,41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,
88030 41201L,41202L,41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,
88031 41211L,41212L,41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,
88032 41221L,41222L,41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,
88033 41231L,41232L,41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,
88034 41241L,41242L,41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,
88035 41251L,41252L,41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,
88036 41261L,41262L,41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,
88037 41271L,41272L,41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,
88038 41281L,41282L,41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,
88039 41291L,41292L,41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,
88040 41301L,41302L,41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,
88041 41311L,41312L,41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,
88042 41321L,41322L,41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,
88043 41331L,41332L,41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,
88044 41341L,41342L,41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,
88045 41351L,41352L,41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,
88046 41361L,41362L,41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,
88047 41371L,41372L,41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,
88048 41381L,41382L,41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,
88049 41391L,41392L,41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,
88050 41401L,41402L,41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,
88051 41411L,41412L,41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,
88052 41421L,41422L,41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,
88053 41431L,41432L,41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,
88054 41441L,41442L,41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,
88055 41451L,41452L,41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,
88056 41461L,41462L,41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,
88057 41471L,41472L,41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,
88058 41481L,41482L,41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,
88059 41491L,41492L,41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,
88060 41501L,41502L,41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,
88061 41511L,41512L,41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,
88062 41521L,41522L,41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,
88063 41531L,41532L,41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,
88064 41541L,41542L,41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,
88065 41551L,41552L,41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,
88066 41561L,41562L,41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,
88067 41571L,41572L,41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,
88068 41581L,41582L,41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,
88069 41591L,41592L,41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,
88070 41601L,41602L,41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,
88071 41611L,41612L,41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,
88072 41621L,41622L,41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,
88073 41631L,41632L,41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,
88074 41641L,41642L,41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,
88075 41651L,41652L,41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,
88076 41661L,41662L,41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,
88077 41671L,41672L,41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,
88078 41681L,41682L,41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,
88079 41691L,41692L,41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,
88080 41701L,41702L,41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,
88081 41711L,41712L,41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,
88082 41721L,41722L,41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,
88083 41731L,41732L,41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,
88084 41741L,41742L,41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,
88085 41751L,41752L,41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,
88086 41761L,41762L,41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,
88087 41771L,41772L,41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,
88088 41781L,41782L,41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,
88089 41791L,41792L,41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,
88090 41801L,41802L,41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,
88091 41811L,41812L,41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,
88092 41821L,41822L,41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,
88093 41831L,41832L,41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,
88094 41841L,41842L,41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,
88095 41851L,41852L,41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,
88096 41861L,41862L,41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,
88097 41871L,41872L,41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,
88098 41881L,41882L,41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,
88099 41891L,41892L,41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,
88100 41901L,41902L,41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,
88101 41911L,41912L,41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,
88102 41921L,41922L,41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,
88103 41931L,41932L,41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,
88104 41941L,41942L,41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,
88105 41951L,41952L,41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,
88106 41961L,41962L,41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,
88107 41971L,41972L,41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,
88108 41981L,41982L,41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,
88109 41991L,41992L,41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,
88110 42001L,42002L,42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,
88111 42011L,42012L,42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,
88112 42021L,42022L,42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,
88113 42031L,42032L,42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,
88114 42041L,42042L,42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,
88115 42051L,42052L,42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,
88116 42061L,42062L,42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,
88117 42071L,42072L,42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,
88118 42081L,42082L,42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,
88119 42091L,42092L,42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,
88120 42101L,42102L,42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,
88121 42111L,42112L,42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,
88122 42121L,42122L,42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,
88123 42131L,42132L,42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,
88124 42141L,42142L,42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,
88125 42151L,42152L,42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,
88126 42161L,42162L,42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,
88127 42171L,42172L,42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,
88128 42181L,42182L,42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,
88129 42191L,42192L,42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,
88130 42201L,42202L,42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,
88131 42211L,42212L,42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,
88132 42221L,42222L,42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,
88133 42231L,42232L,42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,
88134 42241L,42242L,42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,
88135 42251L,42252L,42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,
88136 42261L,42262L,42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,
88137 42271L,42272L,42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,
88138 42281L,42282L,42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,
88139 42291L,42292L,42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,
88140 42301L,42302L,42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,
88141 42311L,42312L,42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,
88142 42321L,42322L,42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,
88143 42331L,42332L,42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,
88144 42341L,42342L,42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,
88145 42351L,42352L,42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,
88146 42361L,42362L,42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,
88147 42371L,42372L,42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,
88148 42381L,42382L,42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,
88149 42391L,42392L,42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,
88150 42401L,42402L,42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,
88151 42411L,42412L,42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,
88152 42421L,42422L,42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,
88153 42431L,42432L,42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,
88154 42441L,42442L,42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,
88155 42451L,42452L,42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,
88156 42461L,42462L,42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,
88157 42471L,42472L,42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,
88158 42481L,42482L,42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,
88159 42491L,42492L,42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,
88160 42501L,42502L,42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,
88161 42511L,42512L,42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,
88162 42521L,42522L,42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,
88163 42531L,42532L,42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,
88164 42541L,42542L,42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,
88165 42551L,42552L,42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,
88166 42560L,42562L,42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,
88167 42570L,42572L,42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,
88168 42580L,42582L,42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,
88169 42590L,42592L,42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,
88170 42600L,42602L,42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,
88171 42611L,42612L,42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,
88172 42621L,42622L,42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,
88173 42630L,42632L,42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,
88174 42640L,42642L,42642L,42644L,42644L,42646L,42646L,42648L,42648L,42650L,
88175 42650L,42652L,42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,
88176 42661L,42662L,42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,
88177 42671L,42672L,42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,
88178 42681L,42682L,42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,
88179 42691L,42692L,42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,
88180 42701L,42702L,42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,
88181 42711L,42712L,42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,
88182 42721L,42722L,42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,
88183 42731L,42732L,42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,
88184 42741L,42742L,42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,
88185 42751L,42752L,42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,
88186 42761L,42762L,42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,
88187 42771L,42772L,42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,
88188 42781L,42782L,42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,
88189 42790L,42792L,42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,
88190 42801L,42802L,42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,
88191 42810L,42812L,42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,
88192 42820L,42822L,42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,
88193 42830L,42832L,42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,
88194 42840L,42842L,42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,
88195 42850L,42852L,42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,
88196 42860L,42862L,42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,
88197 42871L,42872L,42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,
88198 42880L,42882L,42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,
88199 42891L,42891L,42893L,42894L,42895L,42896L,42896L,42898L,42898L,42900L,
88200 42901L,42902L,42902L,42904L,42904L,42906L,42906L,42908L,42908L,42910L,
88201 42910L,42912L,42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,
88202 42920L,42922L,42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,
88203 42931L,42932L,42932L,42934L,42934L,42936L,42937L,42938L,42939L,42940L,
88204 42941L,42942L,42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,
88205 42951L,42952L,42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,
88206 42961L,42962L,42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,
88207 42971L,42972L,42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,
88208 42981L,42982L,42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,
88209 42991L,42992L,42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,
88210 43001L,43002L,43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,
88211 43011L,43012L,43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,
88212 43021L,43022L,43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,
88213 43031L,43032L,43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,
88214 43041L,43042L,43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,
88215 43051L,43052L,43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,
88216 43061L,43062L,43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,
88217 43071L,43072L,43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,
88218 43081L,43082L,43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,
88219 43091L,43092L,43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,
88220 43101L,43102L,43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,
88221 43111L,43112L,43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,
88222 43121L,43122L,43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,
88223 43131L,43132L,43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,
88224 43141L,43142L,43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,
88225 43151L,43152L,43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,
88226 43161L,43162L,43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,
88227 43171L,43172L,43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,
88228 43181L,43182L,43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,
88229 43191L,43192L,43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,
88230 43201L,43202L,43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,
88231 43211L,43212L,43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,
88232 43221L,43222L,43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,
88233 43231L,43232L,43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,
88234 43241L,43242L,43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,
88235 43251L,43252L,43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,
88236 43261L,43262L,43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,
88237 43271L,43272L,43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,
88238 43281L,43282L,43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,
88239 43291L,43292L,43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,
88240 43301L,43302L,43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,
88241 43311L,43312L,43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,
88242 43321L,43322L,43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,
88243 43331L,43332L,43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,
88244 43341L,43342L,43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,
88245 43351L,43352L,43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,
88246 43361L,43362L,43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,
88247 43371L,43372L,43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,
88248 43381L,43382L,43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,
88249 43391L,43392L,43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,
88250 43401L,43402L,43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,
88251 43411L,43412L,43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,
88252 43421L,43422L,43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,
88253 43431L,43432L,43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,
88254 43441L,43442L,43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,
88255 43451L,43452L,43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,
88256 43461L,43462L,43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,
88257 43471L,43472L,43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,
88258 43481L,43482L,43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,
88259 43491L,43492L,43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,
88260 43501L,43502L,43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,
88261 43511L,43512L,43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,
88262 43521L,43522L,43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,
88263 43531L,43532L,43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,
88264 43541L,43542L,43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,
88265 43551L,43552L,43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,
88266 43561L,43562L,43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,
88267 43571L,43572L,43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,
88268 43581L,43582L,43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,
88269 43591L,43592L,43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,
88270 43601L,43602L,43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,
88271 43611L,43612L,43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,
88272 43621L,43622L,43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,
88273 43631L,43632L,43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,
88274 43641L,43642L,43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,
88275 43651L,43652L,43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,
88276 43661L,43662L,43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,
88277 43671L,43672L,43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,
88278 43681L,43682L,43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,
88279 43691L,43692L,43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,
88280 43701L,43702L,43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,
88281 43711L,43712L,43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,
88282 43721L,43722L,43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,
88283 43731L,43732L,43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,
88284 43741L,43742L,43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,
88285 43751L,43752L,43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,
88286 43761L,43762L,43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,
88287 43771L,43772L,43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,
88288 43781L,43782L,43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,
88289 43791L,43792L,43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,
88290 43801L,43802L,43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,
88291 43811L,43812L,43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,
88292 43821L,43822L,43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,
88293 43831L,43832L,43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,
88294 43841L,43842L,43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,
88295 43851L,43852L,43853L,43854L,43855L,43856L,43857L,43858L,42931L,43860L,
88296 43861L,43862L,43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,
88297 43871L,43872L,43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,
88298 43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,5025,5026,5027,5028,
88299 5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,
88300 5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,
88301 5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,
88302 5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,
88303 5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,
88304 43968L,43969L,43970L,43971L,43972L,43973L,43974L,43975L,43976L,43977L,
88305 43978L,43979L,43980L,43981L,43982L,43983L,43984L,43985L,43986L,43987L,
88306 43988L,43989L,43990L,43991L,43992L,43993L,43994L,43995L,43996L,43997L,
88307 43998L,43999L,44000L,44001L,44002L,44003L,44004L,44005L,44006L,44007L,
88308 44008L,44009L,44010L,44011L,44012L,44013L,44014L,44015L,44016L,44017L,
88309 44018L,44019L,44020L,44021L,44022L,44023L,44024L,44025L,44026L,44027L,
88310 44028L,44029L,44030L,44031L,44032L,44033L,44034L,44035L,44036L,44037L,
88311 44038L,44039L,44040L,44041L,44042L,44043L,44044L,44045L,44046L,44047L,
88312 44048L,44049L,44050L,44051L,44052L,44053L,44054L,44055L,44056L,44057L,
88313 44058L,44059L,44060L,44061L,44062L,44063L,44064L,44065L,44066L,44067L,
88314 44068L,44069L,44070L,44071L,44072L,44073L,44074L,44075L,44076L,44077L,
88315 44078L,44079L,44080L,44081L,44082L,44083L,44084L,44085L,44086L,44087L,
88316 44088L,44089L,44090L,44091L,44092L,44093L,44094L,44095L,44096L,44097L,
88317 44098L,44099L,44100L,44101L,44102L,44103L,44104L,44105L,44106L,44107L,
88318 44108L,44109L,44110L,44111L,44112L,44113L,44114L,44115L,44116L,44117L,
88319 44118L,44119L,44120L,44121L,44122L,44123L,44124L,44125L,44126L,44127L,
88320 44128L,44129L,44130L,44131L,44132L,44133L,44134L,44135L,44136L,44137L,
88321 44138L,44139L,44140L,44141L,44142L,44143L,44144L,44145L,44146L,44147L,
88322 44148L,44149L,44150L,44151L,44152L,44153L,44154L,44155L,44156L,44157L,
88323 44158L,44159L,44160L,44161L,44162L,44163L,44164L,44165L,44166L,44167L,
88324 44168L,44169L,44170L,44171L,44172L,44173L,44174L,44175L,44176L,44177L,
88325 44178L,44179L,44180L,44181L,44182L,44183L,44184L,44185L,44186L,44187L,
88326 44188L,44189L,44190L,44191L,44192L,44193L,44194L,44195L,44196L,44197L,
88327 44198L,44199L,44200L,44201L,44202L,44203L,44204L,44205L,44206L,44207L,
88328 44208L,44209L,44210L,44211L,44212L,44213L,44214L,44215L,44216L,44217L,
88329 44218L,44219L,44220L,44221L,44222L,44223L,44224L,44225L,44226L,44227L,
88330 44228L,44229L,44230L,44231L,44232L,44233L,44234L,44235L,44236L,44237L,
88331 44238L,44239L,44240L,44241L,44242L,44243L,44244L,44245L,44246L,44247L,
88332 44248L,44249L,44250L,44251L,44252L,44253L,44254L,44255L,44256L,44257L,
88333 44258L,44259L,44260L,44261L,44262L,44263L,44264L,44265L,44266L,44267L,
88334 44268L,44269L,44270L,44271L,44272L,44273L,44274L,44275L,44276L,44277L,
88335 44278L,44279L,44280L,44281L,44282L,44283L,44284L,44285L,44286L,44287L,
88336 44288L,44289L,44290L,44291L,44292L,44293L,44294L,44295L,44296L,44297L,
88337 44298L,44299L,44300L,44301L,44302L,44303L,44304L,44305L,44306L,44307L,
88338 44308L,44309L,44310L,44311L,44312L,44313L,44314L,44315L,44316L,44317L,
88339 44318L,44319L,44320L,44321L,44322L,44323L,44324L,44325L,44326L,44327L,
88340 44328L,44329L,44330L,44331L,44332L,44333L,44334L,44335L,44336L,44337L,
88341 44338L,44339L,44340L,44341L,44342L,44343L,44344L,44345L,44346L,44347L,
88342 44348L,44349L,44350L,44351L,44352L,44353L,44354L,44355L,44356L,44357L,
88343 44358L,44359L,44360L,44361L,44362L,44363L,44364L,44365L,44366L,44367L,
88344 44368L,44369L,44370L,44371L,44372L,44373L,44374L,44375L,44376L,44377L,
88345 44378L,44379L,44380L,44381L,44382L,44383L,44384L,44385L,44386L,44387L,
88346 44388L,44389L,44390L,44391L,44392L,44393L,44394L,44395L,44396L,44397L,
88347 44398L,44399L,44400L,44401L,44402L,44403L,44404L,44405L,44406L,44407L,
88348 44408L,44409L,44410L,44411L,44412L,44413L,44414L,44415L,44416L,44417L,
88349 44418L,44419L,44420L,44421L,44422L,44423L,44424L,44425L,44426L,44427L,
88350 44428L,44429L,44430L,44431L,44432L,44433L,44434L,44435L,44436L,44437L,
88351 44438L,44439L,44440L,44441L,44442L,44443L,44444L,44445L,44446L,44447L,
88352 44448L,44449L,44450L,44451L,44452L,44453L,44454L,44455L,44456L,44457L,
88353 44458L,44459L,44460L,44461L,44462L,44463L,44464L,44465L,44466L,44467L,
88354 44468L,44469L,44470L,44471L,44472L,44473L,44474L,44475L,44476L,44477L,
88355 44478L,44479L,44480L,44481L,44482L,44483L,44484L,44485L,44486L,44487L,
88356 44488L,44489L,44490L,44491L,44492L,44493L,44494L,44495L,44496L,44497L,
88357 44498L,44499L,44500L,44501L,44502L,44503L,44504L,44505L,44506L,44507L,
88358 44508L,44509L,44510L,44511L,44512L,44513L,44514L,44515L,44516L,44517L,
88359 44518L,44519L,44520L,44521L,44522L,44523L,44524L,44525L,44526L,44527L,
88360 44528L,44529L,44530L,44531L,44532L,44533L,44534L,44535L,44536L,44537L,
88361 44538L,44539L,44540L,44541L,44542L,44543L,44544L,44545L,44546L,44547L,
88362 44548L,44549L,44550L,44551L,44552L,44553L,44554L,44555L,44556L,44557L,
88363 44558L,44559L,44560L,44561L,44562L,44563L,44564L,44565L,44566L,44567L,
88364 44568L,44569L,44570L,44571L,44572L,44573L,44574L,44575L,44576L,44577L,
88365 44578L,44579L,44580L,44581L,44582L,44583L,44584L,44585L,44586L,44587L,
88366 44588L,44589L,44590L,44591L,44592L,44593L,44594L,44595L,44596L,44597L,
88367 44598L,44599L,44600L,44601L,44602L,44603L,44604L,44605L,44606L,44607L,
88368 44608L,44609L,44610L,44611L,44612L,44613L,44614L,44615L,44616L,44617L,
88369 44618L,44619L,44620L,44621L,44622L,44623L,44624L,44625L,44626L,44627L,
88370 44628L,44629L,44630L,44631L,44632L,44633L,44634L,44635L,44636L,44637L,
88371 44638L,44639L,44640L,44641L,44642L,44643L,44644L,44645L,44646L,44647L,
88372 44648L,44649L,44650L,44651L,44652L,44653L,44654L,44655L,44656L,44657L,
88373 44658L,44659L,44660L,44661L,44662L,44663L,44664L,44665L,44666L,44667L,
88374 44668L,44669L,44670L,44671L,44672L,44673L,44674L,44675L,44676L,44677L,
88375 44678L,44679L,44680L,44681L,44682L,44683L,44684L,44685L,44686L,44687L,
88376 44688L,44689L,44690L,44691L,44692L,44693L,44694L,44695L,44696L,44697L,
88377 44698L,44699L,44700L,44701L,44702L,44703L,44704L,44705L,44706L,44707L,
88378 44708L,44709L,44710L,44711L,44712L,44713L,44714L,44715L,44716L,44717L,
88379 44718L,44719L,44720L,44721L,44722L,44723L,44724L,44725L,44726L,44727L,
88380 44728L,44729L,44730L,44731L,44732L,44733L,44734L,44735L,44736L,44737L,
88381 44738L,44739L,44740L,44741L,44742L,44743L,44744L,44745L,44746L,44747L,
88382 44748L,44749L,44750L,44751L,44752L,44753L,44754L,44755L,44756L,44757L,
88383 44758L,44759L,44760L,44761L,44762L,44763L,44764L,44765L,44766L,44767L,
88384 44768L,44769L,44770L,44771L,44772L,44773L,44774L,44775L,44776L,44777L,
88385 44778L,44779L,44780L,44781L,44782L,44783L,44784L,44785L,44786L,44787L,
88386 44788L,44789L,44790L,44791L,44792L,44793L,44794L,44795L,44796L,44797L,
88387 44798L,44799L,44800L,44801L,44802L,44803L,44804L,44805L,44806L,44807L,
88388 44808L,44809L,44810L,44811L,44812L,44813L,44814L,44815L,44816L,44817L,
88389 44818L,44819L,44820L,44821L,44822L,44823L,44824L,44825L,44826L,44827L,
88390 44828L,44829L,44830L,44831L,44832L,44833L,44834L,44835L,44836L,44837L,
88391 44838L,44839L,44840L,44841L,44842L,44843L,44844L,44845L,44846L,44847L,
88392 44848L,44849L,44850L,44851L,44852L,44853L,44854L,44855L,44856L,44857L,
88393 44858L,44859L,44860L,44861L,44862L,44863L,44864L,44865L,44866L,44867L,
88394 44868L,44869L,44870L,44871L,44872L,44873L,44874L,44875L,44876L,44877L,
88395 44878L,44879L,44880L,44881L,44882L,44883L,44884L,44885L,44886L,44887L,
88396 44888L,44889L,44890L,44891L,44892L,44893L,44894L,44895L,44896L,44897L,
88397 44898L,44899L,44900L,44901L,44902L,44903L,44904L,44905L,44906L,44907L,
88398 44908L,44909L,44910L,44911L,44912L,44913L,44914L,44915L,44916L,44917L,
88399 44918L,44919L,44920L,44921L,44922L,44923L,44924L,44925L,44926L,44927L,
88400 44928L,44929L,44930L,44931L,44932L,44933L,44934L,44935L,44936L,44937L,
88401 44938L,44939L,44940L,44941L,44942L,44943L,44944L,44945L,44946L,44947L,
88402 44948L,44949L,44950L,44951L,44952L,44953L,44954L,44955L,44956L,44957L,
88403 44958L,44959L,44960L,44961L,44962L,44963L,44964L,44965L,44966L,44967L,
88404 44968L,44969L,44970L,44971L,44972L,44973L,44974L,44975L,44976L,44977L,
88405 44978L,44979L,44980L,44981L,44982L,44983L,44984L,44985L,44986L,44987L,
88406 44988L,44989L,44990L,44991L,44992L,44993L,44994L,44995L,44996L,44997L,
88407 44998L,44999L,45000L,45001L,45002L,45003L,45004L,45005L,45006L,45007L,
88408 45008L,45009L,45010L,45011L,45012L,45013L,45014L,45015L,45016L,45017L,
88409 45018L,45019L,45020L,45021L,45022L,45023L,45024L,45025L,45026L,45027L,
88410 45028L,45029L,45030L,45031L,45032L,45033L,45034L,45035L,45036L,45037L,
88411 45038L,45039L,45040L,45041L,45042L,45043L,45044L,45045L,45046L,45047L,
88412 45048L,45049L,45050L,45051L,45052L,45053L,45054L,45055L,45056L,45057L,
88413 45058L,45059L,45060L,45061L,45062L,45063L,45064L,45065L,45066L,45067L,
88414 45068L,45069L,45070L,45071L,45072L,45073L,45074L,45075L,45076L,45077L,
88415 45078L,45079L,45080L,45081L,45082L,45083L,45084L,45085L,45086L,45087L,
88416 45088L,45089L,45090L,45091L,45092L,45093L,45094L,45095L,45096L,45097L,
88417 45098L,45099L,45100L,45101L,45102L,45103L,45104L,45105L,45106L,45107L,
88418 45108L,45109L,45110L,45111L,45112L,45113L,45114L,45115L,45116L,45117L,
88419 45118L,45119L,45120L,45121L,45122L,45123L,45124L,45125L,45126L,45127L,
88420 45128L,45129L,45130L,45131L,45132L,45133L,45134L,45135L,45136L,45137L,
88421 45138L,45139L,45140L,45141L,45142L,45143L,45144L,45145L,45146L,45147L,
88422 45148L,45149L,45150L,45151L,45152L,45153L,45154L,45155L,45156L,45157L,
88423 45158L,45159L,45160L,45161L,45162L,45163L,45164L,45165L,45166L,45167L,
88424 45168L,45169L,45170L,45171L,45172L,45173L,45174L,45175L,45176L,45177L,
88425 45178L,45179L,45180L,45181L,45182L,45183L,45184L,45185L,45186L,45187L,
88426 45188L,45189L,45190L,45191L,45192L,45193L,45194L,45195L,45196L,45197L,
88427 45198L,45199L,45200L,45201L,45202L,45203L,45204L,45205L,45206L,45207L,
88428 45208L,45209L,45210L,45211L,45212L,45213L,45214L,45215L,45216L,45217L,
88429 45218L,45219L,45220L,45221L,45222L,45223L,45224L,45225L,45226L,45227L,
88430 45228L,45229L,45230L,45231L,45232L,45233L,45234L,45235L,45236L,45237L,
88431 45238L,45239L,45240L,45241L,45242L,45243L,45244L,45245L,45246L,45247L,
88432 45248L,45249L,45250L,45251L,45252L,45253L,45254L,45255L,45256L,45257L,
88433 45258L,45259L,45260L,45261L,45262L,45263L,45264L,45265L,45266L,45267L,
88434 45268L,45269L,45270L,45271L,45272L,45273L,45274L,45275L,45276L,45277L,
88435 45278L,45279L,45280L,45281L,45282L,45283L,45284L,45285L,45286L,45287L,
88436 45288L,45289L,45290L,45291L,45292L,45293L,45294L,45295L,45296L,45297L,
88437 45298L,45299L,45300L,45301L,45302L,45303L,45304L,45305L,45306L,45307L,
88438 45308L,45309L,45310L,45311L,45312L,45313L,45314L,45315L,45316L,45317L,
88439 45318L,45319L,45320L,45321L,45322L,45323L,45324L,45325L,45326L,45327L,
88440 45328L,45329L,45330L,45331L,45332L,45333L,45334L,45335L,45336L,45337L,
88441 45338L,45339L,45340L,45341L,45342L,45343L,45344L,45345L,45346L,45347L,
88442 45348L,45349L,45350L,45351L,45352L,45353L,45354L,45355L,45356L,45357L,
88443 45358L,45359L,45360L,45361L,45362L,45363L,45364L,45365L,45366L,45367L,
88444 45368L,45369L,45370L,45371L,45372L,45373L,45374L,45375L,45376L,45377L,
88445 45378L,45379L,45380L,45381L,45382L,45383L,45384L,45385L,45386L,45387L,
88446 45388L,45389L,45390L,45391L,45392L,45393L,45394L,45395L,45396L,45397L,
88447 45398L,45399L,45400L,45401L,45402L,45403L,45404L,45405L,45406L,45407L,
88448 45408L,45409L,45410L,45411L,45412L,45413L,45414L,45415L,45416L,45417L,
88449 45418L,45419L,45420L,45421L,45422L,45423L,45424L,45425L,45426L,45427L,
88450 45428L,45429L,45430L,45431L,45432L,45433L,45434L,45435L,45436L,45437L,
88451 45438L,45439L,45440L,45441L,45442L,45443L,45444L,45445L,45446L,45447L,
88452 45448L,45449L,45450L,45451L,45452L,45453L,45454L,45455L,45456L,45457L,
88453 45458L,45459L,45460L,45461L,45462L,45463L,45464L,45465L,45466L,45467L,
88454 45468L,45469L,45470L,45471L,45472L,45473L,45474L,45475L,45476L,45477L,
88455 45478L,45479L,45480L,45481L,45482L,45483L,45484L,45485L,45486L,45487L,
88456 45488L,45489L,45490L,45491L,45492L,45493L,45494L,45495L,45496L,45497L,
88457 45498L,45499L,45500L,45501L,45502L,45503L,45504L,45505L,45506L,45507L,
88458 45508L,45509L,45510L,45511L,45512L,45513L,45514L,45515L,45516L,45517L,
88459 45518L,45519L,45520L,45521L,45522L,45523L,45524L,45525L,45526L,45527L,
88460 45528L,45529L,45530L,45531L,45532L,45533L,45534L,45535L,45536L,45537L,
88461 45538L,45539L,45540L,45541L,45542L,45543L,45544L,45545L,45546L,45547L,
88462 45548L,45549L,45550L,45551L,45552L,45553L,45554L,45555L,45556L,45557L,
88463 45558L,45559L,45560L,45561L,45562L,45563L,45564L,45565L,45566L,45567L,
88464 45568L,45569L,45570L,45571L,45572L,45573L,45574L,45575L,45576L,45577L,
88465 45578L,45579L,45580L,45581L,45582L,45583L,45584L,45585L,45586L,45587L,
88466 45588L,45589L,45590L,45591L,45592L,45593L,45594L,45595L,45596L,45597L,
88467 45598L,45599L,45600L,45601L,45602L,45603L,45604L,45605L,45606L,45607L,
88468 45608L,45609L,45610L,45611L,45612L,45613L,45614L,45615L,45616L,45617L,
88469 45618L,45619L,45620L,45621L,45622L,45623L,45624L,45625L,45626L,45627L,
88470 45628L,45629L,45630L,45631L,45632L,45633L,45634L,45635L,45636L,45637L,
88471 45638L,45639L,45640L,45641L,45642L,45643L,45644L,45645L,45646L,45647L,
88472 45648L,45649L,45650L,45651L,45652L,45653L,45654L,45655L,45656L,45657L,
88473 45658L,45659L,45660L,45661L,45662L,45663L,45664L,45665L,45666L,45667L,
88474 45668L,45669L,45670L,45671L,45672L,45673L,45674L,45675L,45676L,45677L,
88475 45678L,45679L,45680L,45681L,45682L,45683L,45684L,45685L,45686L,45687L,
88476 45688L,45689L,45690L,45691L,45692L,45693L,45694L,45695L,45696L,45697L,
88477 45698L,45699L,45700L,45701L,45702L,45703L,45704L,45705L,45706L,45707L,
88478 45708L,45709L,45710L,45711L,45712L,45713L,45714L,45715L,45716L,45717L,
88479 45718L,45719L,45720L,45721L,45722L,45723L,45724L,45725L,45726L,45727L,
88480 45728L,45729L,45730L,45731L,45732L,45733L,45734L,45735L,45736L,45737L,
88481 45738L,45739L,45740L,45741L,45742L,45743L,45744L,45745L,45746L,45747L,
88482 45748L,45749L,45750L,45751L,45752L,45753L,45754L,45755L,45756L,45757L,
88483 45758L,45759L,45760L,45761L,45762L,45763L,45764L,45765L,45766L,45767L,
88484 45768L,45769L,45770L,45771L,45772L,45773L,45774L,45775L,45776L,45777L,
88485 45778L,45779L,45780L,45781L,45782L,45783L,45784L,45785L,45786L,45787L,
88486 45788L,45789L,45790L,45791L,45792L,45793L,45794L,45795L,45796L,45797L,
88487 45798L,45799L,45800L,45801L,45802L,45803L,45804L,45805L,45806L,45807L,
88488 45808L,45809L,45810L,45811L,45812L,45813L,45814L,45815L,45816L,45817L,
88489 45818L,45819L,45820L,45821L,45822L,45823L,45824L,45825L,45826L,45827L,
88490 45828L,45829L,45830L,45831L,45832L,45833L,45834L,45835L,45836L,45837L,
88491 45838L,45839L,45840L,45841L,45842L,45843L,45844L,45845L,45846L,45847L,
88492 45848L,45849L,45850L,45851L,45852L,45853L,45854L,45855L,45856L,45857L,
88493 45858L,45859L,45860L,45861L,45862L,45863L,45864L,45865L,45866L,45867L,
88494 45868L,45869L,45870L,45871L,45872L,45873L,45874L,45875L,45876L,45877L,
88495 45878L,45879L,45880L,45881L,45882L,45883L,45884L,45885L,45886L,45887L,
88496 45888L,45889L,45890L,45891L,45892L,45893L,45894L,45895L,45896L,45897L,
88497 45898L,45899L,45900L,45901L,45902L,45903L,45904L,45905L,45906L,45907L,
88498 45908L,45909L,45910L,45911L,45912L,45913L,45914L,45915L,45916L,45917L,
88499 45918L,45919L,45920L,45921L,45922L,45923L,45924L,45925L,45926L,45927L,
88500 45928L,45929L,45930L,45931L,45932L,45933L,45934L,45935L,45936L,45937L,
88501 45938L,45939L,45940L,45941L,45942L,45943L,45944L,45945L,45946L,45947L,
88502 45948L,45949L,45950L,45951L,45952L,45953L,45954L,45955L,45956L,45957L,
88503 45958L,45959L,45960L,45961L,45962L,45963L,45964L,45965L,45966L,45967L,
88504 45968L,45969L,45970L,45971L,45972L,45973L,45974L,45975L,45976L,45977L,
88505 45978L,45979L,45980L,45981L,45982L,45983L,45984L,45985L,45986L,45987L,
88506 45988L,45989L,45990L,45991L,45992L,45993L,45994L,45995L,45996L,45997L,
88507 45998L,45999L,46000L,46001L,46002L,46003L,46004L,46005L,46006L,46007L,
88508 46008L,46009L,46010L,46011L,46012L,46013L,46014L,46015L,46016L,46017L,
88509 46018L,46019L,46020L,46021L,46022L,46023L,46024L,46025L,46026L,46027L,
88510 46028L,46029L,46030L,46031L,46032L,46033L,46034L,46035L,46036L,46037L,
88511 46038L,46039L,46040L,46041L,46042L,46043L,46044L,46045L,46046L,46047L,
88512 46048L,46049L,46050L,46051L,46052L,46053L,46054L,46055L,46056L,46057L,
88513 46058L,46059L,46060L,46061L,46062L,46063L,46064L,46065L,46066L,46067L,
88514 46068L,46069L,46070L,46071L,46072L,46073L,46074L,46075L,46076L,46077L,
88515 46078L,46079L,46080L,46081L,46082L,46083L,46084L,46085L,46086L,46087L,
88516 46088L,46089L,46090L,46091L,46092L,46093L,46094L,46095L,46096L,46097L,
88517 46098L,46099L,46100L,46101L,46102L,46103L,46104L,46105L,46106L,46107L,
88518 46108L,46109L,46110L,46111L,46112L,46113L,46114L,46115L,46116L,46117L,
88519 46118L,46119L,46120L,46121L,46122L,46123L,46124L,46125L,46126L,46127L,
88520 46128L,46129L,46130L,46131L,46132L,46133L,46134L,46135L,46136L,46137L,
88521 46138L,46139L,46140L,46141L,46142L,46143L,46144L,46145L,46146L,46147L,
88522 46148L,46149L,46150L,46151L,46152L,46153L,46154L,46155L,46156L,46157L,
88523 46158L,46159L,46160L,46161L,46162L,46163L,46164L,46165L,46166L,46167L,
88524 46168L,46169L,46170L,46171L,46172L,46173L,46174L,46175L,46176L,46177L,
88525 46178L,46179L,46180L,46181L,46182L,46183L,46184L,46185L,46186L,46187L,
88526 46188L,46189L,46190L,46191L,46192L,46193L,46194L,46195L,46196L,46197L,
88527 46198L,46199L,46200L,46201L,46202L,46203L,46204L,46205L,46206L,46207L,
88528 46208L,46209L,46210L,46211L,46212L,46213L,46214L,46215L,46216L,46217L,
88529 46218L,46219L,46220L,46221L,46222L,46223L,46224L,46225L,46226L,46227L,
88530 46228L,46229L,46230L,46231L,46232L,46233L,46234L,46235L,46236L,46237L,
88531 46238L,46239L,46240L,46241L,46242L,46243L,46244L,46245L,46246L,46247L,
88532 46248L,46249L,46250L,46251L,46252L,46253L,46254L,46255L,46256L,46257L,
88533 46258L,46259L,46260L,46261L,46262L,46263L,46264L,46265L,46266L,46267L,
88534 46268L,46269L,46270L,46271L,46272L,46273L,46274L,46275L,46276L,46277L,
88535 46278L,46279L,46280L,46281L,46282L,46283L,46284L,46285L,46286L,46287L,
88536 46288L,46289L,46290L,46291L,46292L,46293L,46294L,46295L,46296L,46297L,
88537 46298L,46299L,46300L,46301L,46302L,46303L,46304L,46305L,46306L,46307L,
88538 46308L,46309L,46310L,46311L,46312L,46313L,46314L,46315L,46316L,46317L,
88539 46318L,46319L,46320L,46321L,46322L,46323L,46324L,46325L,46326L,46327L,
88540 46328L,46329L,46330L,46331L,46332L,46333L,46334L,46335L,46336L,46337L,
88541 46338L,46339L,46340L,46341L,46342L,46343L,46344L,46345L,46346L,46347L,
88542 46348L,46349L,46350L,46351L,46352L,46353L,46354L,46355L,46356L,46357L,
88543 46358L,46359L,46360L,46361L,46362L,46363L,46364L,46365L,46366L,46367L,
88544 46368L,46369L,46370L,46371L,46372L,46373L,46374L,46375L,46376L,46377L,
88545 46378L,46379L,46380L,46381L,46382L,46383L,46384L,46385L,46386L,46387L,
88546 46388L,46389L,46390L,46391L,46392L,46393L,46394L,46395L,46396L,46397L,
88547 46398L,46399L,46400L,46401L,46402L,46403L,46404L,46405L,46406L,46407L,
88548 46408L,46409L,46410L,46411L,46412L,46413L,46414L,46415L,46416L,46417L,
88549 46418L,46419L,46420L,46421L,46422L,46423L,46424L,46425L,46426L,46427L,
88550 46428L,46429L,46430L,46431L,46432L,46433L,46434L,46435L,46436L,46437L,
88551 46438L,46439L,46440L,46441L,46442L,46443L,46444L,46445L,46446L,46447L,
88552 46448L,46449L,46450L,46451L,46452L,46453L,46454L,46455L,46456L,46457L,
88553 46458L,46459L,46460L,46461L,46462L,46463L,46464L,46465L,46466L,46467L,
88554 46468L,46469L,46470L,46471L,46472L,46473L,46474L,46475L,46476L,46477L,
88555 46478L,46479L,46480L,46481L,46482L,46483L,46484L,46485L,46486L,46487L,
88556 46488L,46489L,46490L,46491L,46492L,46493L,46494L,46495L,46496L,46497L,
88557 46498L,46499L,46500L,46501L,46502L,46503L,46504L,46505L,46506L,46507L,
88558 46508L,46509L,46510L,46511L,46512L,46513L,46514L,46515L,46516L,46517L,
88559 46518L,46519L,46520L,46521L,46522L,46523L,46524L,46525L,46526L,46527L,
88560 46528L,46529L,46530L,46531L,46532L,46533L,46534L,46535L,46536L,46537L,
88561 46538L,46539L,46540L,46541L,46542L,46543L,46544L,46545L,46546L,46547L,
88562 46548L,46549L,46550L,46551L,46552L,46553L,46554L,46555L,46556L,46557L,
88563 46558L,46559L,46560L,46561L,46562L,46563L,46564L,46565L,46566L,46567L,
88564 46568L,46569L,46570L,46571L,46572L,46573L,46574L,46575L,46576L,46577L,
88565 46578L,46579L,46580L,46581L,46582L,46583L,46584L,46585L,46586L,46587L,
88566 46588L,46589L,46590L,46591L,46592L,46593L,46594L,46595L,46596L,46597L,
88567 46598L,46599L,46600L,46601L,46602L,46603L,46604L,46605L,46606L,46607L,
88568 46608L,46609L,46610L,46611L,46612L,46613L,46614L,46615L,46616L,46617L,
88569 46618L,46619L,46620L,46621L,46622L,46623L,46624L,46625L,46626L,46627L,
88570 46628L,46629L,46630L,46631L,46632L,46633L,46634L,46635L,46636L,46637L,
88571 46638L,46639L,46640L,46641L,46642L,46643L,46644L,46645L,46646L,46647L,
88572 46648L,46649L,46650L,46651L,46652L,46653L,46654L,46655L,46656L,46657L,
88573 46658L,46659L,46660L,46661L,46662L,46663L,46664L,46665L,46666L,46667L,
88574 46668L,46669L,46670L,46671L,46672L,46673L,46674L,46675L,46676L,46677L,
88575 46678L,46679L,46680L,46681L,46682L,46683L,46684L,46685L,46686L,46687L,
88576 46688L,46689L,46690L,46691L,46692L,46693L,46694L,46695L,46696L,46697L,
88577 46698L,46699L,46700L,46701L,46702L,46703L,46704L,46705L,46706L,46707L,
88578 46708L,46709L,46710L,46711L,46712L,46713L,46714L,46715L,46716L,46717L,
88579 46718L,46719L,46720L,46721L,46722L,46723L,46724L,46725L,46726L,46727L,
88580 46728L,46729L,46730L,46731L,46732L,46733L,46734L,46735L,46736L,46737L,
88581 46738L,46739L,46740L,46741L,46742L,46743L,46744L,46745L,46746L,46747L,
88582 46748L,46749L,46750L,46751L,46752L,46753L,46754L,46755L,46756L,46757L,
88583 46758L,46759L,46760L,46761L,46762L,46763L,46764L,46765L,46766L,46767L,
88584 46768L,46769L,46770L,46771L,46772L,46773L,46774L,46775L,46776L,46777L,
88585 46778L,46779L,46780L,46781L,46782L,46783L,46784L,46785L,46786L,46787L,
88586 46788L,46789L,46790L,46791L,46792L,46793L,46794L,46795L,46796L,46797L,
88587 46798L,46799L,46800L,46801L,46802L,46803L,46804L,46805L,46806L,46807L,
88588 46808L,46809L,46810L,46811L,46812L,46813L,46814L,46815L,46816L,46817L,
88589 46818L,46819L,46820L,46821L,46822L,46823L,46824L,46825L,46826L,46827L,
88590 46828L,46829L,46830L,46831L,46832L,46833L,46834L,46835L,46836L,46837L,
88591 46838L,46839L,46840L,46841L,46842L,46843L,46844L,46845L,46846L,46847L,
88592 46848L,46849L,46850L,46851L,46852L,46853L,46854L,46855L,46856L,46857L,
88593 46858L,46859L,46860L,46861L,46862L,46863L,46864L,46865L,46866L,46867L,
88594 46868L,46869L,46870L,46871L,46872L,46873L,46874L,46875L,46876L,46877L,
88595 46878L,46879L,46880L,46881L,46882L,46883L,46884L,46885L,46886L,46887L,
88596 46888L,46889L,46890L,46891L,46892L,46893L,46894L,46895L,46896L,46897L,
88597 46898L,46899L,46900L,46901L,46902L,46903L,46904L,46905L,46906L,46907L,
88598 46908L,46909L,46910L,46911L,46912L,46913L,46914L,46915L,46916L,46917L,
88599 46918L,46919L,46920L,46921L,46922L,46923L,46924L,46925L,46926L,46927L,
88600 46928L,46929L,46930L,46931L,46932L,46933L,46934L,46935L,46936L,46937L,
88601 46938L,46939L,46940L,46941L,46942L,46943L,46944L,46945L,46946L,46947L,
88602 46948L,46949L,46950L,46951L,46952L,46953L,46954L,46955L,46956L,46957L,
88603 46958L,46959L,46960L,46961L,46962L,46963L,46964L,46965L,46966L,46967L,
88604 46968L,46969L,46970L,46971L,46972L,46973L,46974L,46975L,46976L,46977L,
88605 46978L,46979L,46980L,46981L,46982L,46983L,46984L,46985L,46986L,46987L,
88606 46988L,46989L,46990L,46991L,46992L,46993L,46994L,46995L,46996L,46997L,
88607 46998L,46999L,47000L,47001L,47002L,47003L,47004L,47005L,47006L,47007L,
88608 47008L,47009L,47010L,47011L,47012L,47013L,47014L,47015L,47016L,47017L,
88609 47018L,47019L,47020L,47021L,47022L,47023L,47024L,47025L,47026L,47027L,
88610 47028L,47029L,47030L,47031L,47032L,47033L,47034L,47035L,47036L,47037L,
88611 47038L,47039L,47040L,47041L,47042L,47043L,47044L,47045L,47046L,47047L,
88612 47048L,47049L,47050L,47051L,47052L,47053L,47054L,47055L,47056L,47057L,
88613 47058L,47059L,47060L,47061L,47062L,47063L,47064L,47065L,47066L,47067L,
88614 47068L,47069L,47070L,47071L,47072L,47073L,47074L,47075L,47076L,47077L,
88615 47078L,47079L,47080L,47081L,47082L,47083L,47084L,47085L,47086L,47087L,
88616 47088L,47089L,47090L,47091L,47092L,47093L,47094L,47095L,47096L,47097L,
88617 47098L,47099L,47100L,47101L,47102L,47103L,47104L,47105L,47106L,47107L,
88618 47108L,47109L,47110L,47111L,47112L,47113L,47114L,47115L,47116L,47117L,
88619 47118L,47119L,47120L,47121L,47122L,47123L,47124L,47125L,47126L,47127L,
88620 47128L,47129L,47130L,47131L,47132L,47133L,47134L,47135L,47136L,47137L,
88621 47138L,47139L,47140L,47141L,47142L,47143L,47144L,47145L,47146L,47147L,
88622 47148L,47149L,47150L,47151L,47152L,47153L,47154L,47155L,47156L,47157L,
88623 47158L,47159L,47160L,47161L,47162L,47163L,47164L,47165L,47166L,47167L,
88624 47168L,47169L,47170L,47171L,47172L,47173L,47174L,47175L,47176L,47177L,
88625 47178L,47179L,47180L,47181L,47182L,47183L,47184L,47185L,47186L,47187L,
88626 47188L,47189L,47190L,47191L,47192L,47193L,47194L,47195L,47196L,47197L,
88627 47198L,47199L,47200L,47201L,47202L,47203L,47204L,47205L,47206L,47207L,
88628 47208L,47209L,47210L,47211L,47212L,47213L,47214L,47215L,47216L,47217L,
88629 47218L,47219L,47220L,47221L,47222L,47223L,47224L,47225L,47226L,47227L,
88630 47228L,47229L,47230L,47231L,47232L,47233L,47234L,47235L,47236L,47237L,
88631 47238L,47239L,47240L,47241L,47242L,47243L,47244L,47245L,47246L,47247L,
88632 47248L,47249L,47250L,47251L,47252L,47253L,47254L,47255L,47256L,47257L,
88633 47258L,47259L,47260L,47261L,47262L,47263L,47264L,47265L,47266L,47267L,
88634 47268L,47269L,47270L,47271L,47272L,47273L,47274L,47275L,47276L,47277L,
88635 47278L,47279L,47280L,47281L,47282L,47283L,47284L,47285L,47286L,47287L,
88636 47288L,47289L,47290L,47291L,47292L,47293L,47294L,47295L,47296L,47297L,
88637 47298L,47299L,47300L,47301L,47302L,47303L,47304L,47305L,47306L,47307L,
88638 47308L,47309L,47310L,47311L,47312L,47313L,47314L,47315L,47316L,47317L,
88639 47318L,47319L,47320L,47321L,47322L,47323L,47324L,47325L,47326L,47327L,
88640 47328L,47329L,47330L,47331L,47332L,47333L,47334L,47335L,47336L,47337L,
88641 47338L,47339L,47340L,47341L,47342L,47343L,47344L,47345L,47346L,47347L,
88642 47348L,47349L,47350L,47351L,47352L,47353L,47354L,47355L,47356L,47357L,
88643 47358L,47359L,47360L,47361L,47362L,47363L,47364L,47365L,47366L,47367L,
88644 47368L,47369L,47370L,47371L,47372L,47373L,47374L,47375L,47376L,47377L,
88645 47378L,47379L,47380L,47381L,47382L,47383L,47384L,47385L,47386L,47387L,
88646 47388L,47389L,47390L,47391L,47392L,47393L,47394L,47395L,47396L,47397L,
88647 47398L,47399L,47400L,47401L,47402L,47403L,47404L,47405L,47406L,47407L,
88648 47408L,47409L,47410L,47411L,47412L,47413L,47414L,47415L,47416L,47417L,
88649 47418L,47419L,47420L,47421L,47422L,47423L,47424L,47425L,47426L,47427L,
88650 47428L,47429L,47430L,47431L,47432L,47433L,47434L,47435L,47436L,47437L,
88651 47438L,47439L,47440L,47441L,47442L,47443L,47444L,47445L,47446L,47447L,
88652 47448L,47449L,47450L,47451L,47452L,47453L,47454L,47455L,47456L,47457L,
88653 47458L,47459L,47460L,47461L,47462L,47463L,47464L,47465L,47466L,47467L,
88654 47468L,47469L,47470L,47471L,47472L,47473L,47474L,47475L,47476L,47477L,
88655 47478L,47479L,47480L,47481L,47482L,47483L,47484L,47485L,47486L,47487L,
88656 47488L,47489L,47490L,47491L,47492L,47493L,47494L,47495L,47496L,47497L,
88657 47498L,47499L,47500L,47501L,47502L,47503L,47504L,47505L,47506L,47507L,
88658 47508L,47509L,47510L,47511L,47512L,47513L,47514L,47515L,47516L,47517L,
88659 47518L,47519L,47520L,47521L,47522L,47523L,47524L,47525L,47526L,47527L,
88660 47528L,47529L,47530L,47531L,47532L,47533L,47534L,47535L,47536L,47537L,
88661 47538L,47539L,47540L,47541L,47542L,47543L,47544L,47545L,47546L,47547L,
88662 47548L,47549L,47550L,47551L,47552L,47553L,47554L,47555L,47556L,47557L,
88663 47558L,47559L,47560L,47561L,47562L,47563L,47564L,47565L,47566L,47567L,
88664 47568L,47569L,47570L,47571L,47572L,47573L,47574L,47575L,47576L,47577L,
88665 47578L,47579L,47580L,47581L,47582L,47583L,47584L,47585L,47586L,47587L,
88666 47588L,47589L,47590L,47591L,47592L,47593L,47594L,47595L,47596L,47597L,
88667 47598L,47599L,47600L,47601L,47602L,47603L,47604L,47605L,47606L,47607L,
88668 47608L,47609L,47610L,47611L,47612L,47613L,47614L,47615L,47616L,47617L,
88669 47618L,47619L,47620L,47621L,47622L,47623L,47624L,47625L,47626L,47627L,
88670 47628L,47629L,47630L,47631L,47632L,47633L,47634L,47635L,47636L,47637L,
88671 47638L,47639L,47640L,47641L,47642L,47643L,47644L,47645L,47646L,47647L,
88672 47648L,47649L,47650L,47651L,47652L,47653L,47654L,47655L,47656L,47657L,
88673 47658L,47659L,47660L,47661L,47662L,47663L,47664L,47665L,47666L,47667L,
88674 47668L,47669L,47670L,47671L,47672L,47673L,47674L,47675L,47676L,47677L,
88675 47678L,47679L,47680L,47681L,47682L,47683L,47684L,47685L,47686L,47687L,
88676 47688L,47689L,47690L,47691L,47692L,47693L,47694L,47695L,47696L,47697L,
88677 47698L,47699L,47700L,47701L,47702L,47703L,47704L,47705L,47706L,47707L,
88678 47708L,47709L,47710L,47711L,47712L,47713L,47714L,47715L,47716L,47717L,
88679 47718L,47719L,47720L,47721L,47722L,47723L,47724L,47725L,47726L,47727L,
88680 47728L,47729L,47730L,47731L,47732L,47733L,47734L,47735L,47736L,47737L,
88681 47738L,47739L,47740L,47741L,47742L,47743L,47744L,47745L,47746L,47747L,
88682 47748L,47749L,47750L,47751L,47752L,47753L,47754L,47755L,47756L,47757L,
88683 47758L,47759L,47760L,47761L,47762L,47763L,47764L,47765L,47766L,47767L,
88684 47768L,47769L,47770L,47771L,47772L,47773L,47774L,47775L,47776L,47777L,
88685 47778L,47779L,47780L,47781L,47782L,47783L,47784L,47785L,47786L,47787L,
88686 47788L,47789L,47790L,47791L,47792L,47793L,47794L,47795L,47796L,47797L,
88687 47798L,47799L,47800L,47801L,47802L,47803L,47804L,47805L,47806L,47807L,
88688 47808L,47809L,47810L,47811L,47812L,47813L,47814L,47815L,47816L,47817L,
88689 47818L,47819L,47820L,47821L,47822L,47823L,47824L,47825L,47826L,47827L,
88690 47828L,47829L,47830L,47831L,47832L,47833L,47834L,47835L,47836L,47837L,
88691 47838L,47839L,47840L,47841L,47842L,47843L,47844L,47845L,47846L,47847L,
88692 47848L,47849L,47850L,47851L,47852L,47853L,47854L,47855L,47856L,47857L,
88693 47858L,47859L,47860L,47861L,47862L,47863L,47864L,47865L,47866L,47867L,
88694 47868L,47869L,47870L,47871L,47872L,47873L,47874L,47875L,47876L,47877L,
88695 47878L,47879L,47880L,47881L,47882L,47883L,47884L,47885L,47886L,47887L,
88696 47888L,47889L,47890L,47891L,47892L,47893L,47894L,47895L,47896L,47897L,
88697 47898L,47899L,47900L,47901L,47902L,47903L,47904L,47905L,47906L,47907L,
88698 47908L,47909L,47910L,47911L,47912L,47913L,47914L,47915L,47916L,47917L,
88699 47918L,47919L,47920L,47921L,47922L,47923L,47924L,47925L,47926L,47927L,
88700 47928L,47929L,47930L,47931L,47932L,47933L,47934L,47935L,47936L,47937L,
88701 47938L,47939L,47940L,47941L,47942L,47943L,47944L,47945L,47946L,47947L,
88702 47948L,47949L,47950L,47951L,47952L,47953L,47954L,47955L,47956L,47957L,
88703 47958L,47959L,47960L,47961L,47962L,47963L,47964L,47965L,47966L,47967L,
88704 47968L,47969L,47970L,47971L,47972L,47973L,47974L,47975L,47976L,47977L,
88705 47978L,47979L,47980L,47981L,47982L,47983L,47984L,47985L,47986L,47987L,
88706 47988L,47989L,47990L,47991L,47992L,47993L,47994L,47995L,47996L,47997L,
88707 47998L,47999L,48000L,48001L,48002L,48003L,48004L,48005L,48006L,48007L,
88708 48008L,48009L,48010L,48011L,48012L,48013L,48014L,48015L,48016L,48017L,
88709 48018L,48019L,48020L,48021L,48022L,48023L,48024L,48025L,48026L,48027L,
88710 48028L,48029L,48030L,48031L,48032L,48033L,48034L,48035L,48036L,48037L,
88711 48038L,48039L,48040L,48041L,48042L,48043L,48044L,48045L,48046L,48047L,
88712 48048L,48049L,48050L,48051L,48052L,48053L,48054L,48055L,48056L,48057L,
88713 48058L,48059L,48060L,48061L,48062L,48063L,48064L,48065L,48066L,48067L,
88714 48068L,48069L,48070L,48071L,48072L,48073L,48074L,48075L,48076L,48077L,
88715 48078L,48079L,48080L,48081L,48082L,48083L,48084L,48085L,48086L,48087L,
88716 48088L,48089L,48090L,48091L,48092L,48093L,48094L,48095L,48096L,48097L,
88717 48098L,48099L,48100L,48101L,48102L,48103L,48104L,48105L,48106L,48107L,
88718 48108L,48109L,48110L,48111L,48112L,48113L,48114L,48115L,48116L,48117L,
88719 48118L,48119L,48120L,48121L,48122L,48123L,48124L,48125L,48126L,48127L,
88720 48128L,48129L,48130L,48131L,48132L,48133L,48134L,48135L,48136L,48137L,
88721 48138L,48139L,48140L,48141L,48142L,48143L,48144L,48145L,48146L,48147L,
88722 48148L,48149L,48150L,48151L,48152L,48153L,48154L,48155L,48156L,48157L,
88723 48158L,48159L,48160L,48161L,48162L,48163L,48164L,48165L,48166L,48167L,
88724 48168L,48169L,48170L,48171L,48172L,48173L,48174L,48175L,48176L,48177L,
88725 48178L,48179L,48180L,48181L,48182L,48183L,48184L,48185L,48186L,48187L,
88726 48188L,48189L,48190L,48191L,48192L,48193L,48194L,48195L,48196L,48197L,
88727 48198L,48199L,48200L,48201L,48202L,48203L,48204L,48205L,48206L,48207L,
88728 48208L,48209L,48210L,48211L,48212L,48213L,48214L,48215L,48216L,48217L,
88729 48218L,48219L,48220L,48221L,48222L,48223L,48224L,48225L,48226L,48227L,
88730 48228L,48229L,48230L,48231L,48232L,48233L,48234L,48235L,48236L,48237L,
88731 48238L,48239L,48240L,48241L,48242L,48243L,48244L,48245L,48246L,48247L,
88732 48248L,48249L,48250L,48251L,48252L,48253L,48254L,48255L,48256L,48257L,
88733 48258L,48259L,48260L,48261L,48262L,48263L,48264L,48265L,48266L,48267L,
88734 48268L,48269L,48270L,48271L,48272L,48273L,48274L,48275L,48276L,48277L,
88735 48278L,48279L,48280L,48281L,48282L,48283L,48284L,48285L,48286L,48287L,
88736 48288L,48289L,48290L,48291L,48292L,48293L,48294L,48295L,48296L,48297L,
88737 48298L,48299L,48300L,48301L,48302L,48303L,48304L,48305L,48306L,48307L,
88738 48308L,48309L,48310L,48311L,48312L,48313L,48314L,48315L,48316L,48317L,
88739 48318L,48319L,48320L,48321L,48322L,48323L,48324L,48325L,48326L,48327L,
88740 48328L,48329L,48330L,48331L,48332L,48333L,48334L,48335L,48336L,48337L,
88741 48338L,48339L,48340L,48341L,48342L,48343L,48344L,48345L,48346L,48347L,
88742 48348L,48349L,48350L,48351L,48352L,48353L,48354L,48355L,48356L,48357L,
88743 48358L,48359L,48360L,48361L,48362L,48363L,48364L,48365L,48366L,48367L,
88744 48368L,48369L,48370L,48371L,48372L,48373L,48374L,48375L,48376L,48377L,
88745 48378L,48379L,48380L,48381L,48382L,48383L,48384L,48385L,48386L,48387L,
88746 48388L,48389L,48390L,48391L,48392L,48393L,48394L,48395L,48396L,48397L,
88747 48398L,48399L,48400L,48401L,48402L,48403L,48404L,48405L,48406L,48407L,
88748 48408L,48409L,48410L,48411L,48412L,48413L,48414L,48415L,48416L,48417L,
88749 48418L,48419L,48420L,48421L,48422L,48423L,48424L,48425L,48426L,48427L,
88750 48428L,48429L,48430L,48431L,48432L,48433L,48434L,48435L,48436L,48437L,
88751 48438L,48439L,48440L,48441L,48442L,48443L,48444L,48445L,48446L,48447L,
88752 48448L,48449L,48450L,48451L,48452L,48453L,48454L,48455L,48456L,48457L,
88753 48458L,48459L,48460L,48461L,48462L,48463L,48464L,48465L,48466L,48467L,
88754 48468L,48469L,48470L,48471L,48472L,48473L,48474L,48475L,48476L,48477L,
88755 48478L,48479L,48480L,48481L,48482L,48483L,48484L,48485L,48486L,48487L,
88756 48488L,48489L,48490L,48491L,48492L,48493L,48494L,48495L,48496L,48497L,
88757 48498L,48499L,48500L,48501L,48502L,48503L,48504L,48505L,48506L,48507L,
88758 48508L,48509L,48510L,48511L,48512L,48513L,48514L,48515L,48516L,48517L,
88759 48518L,48519L,48520L,48521L,48522L,48523L,48524L,48525L,48526L,48527L,
88760 48528L,48529L,48530L,48531L,48532L,48533L,48534L,48535L,48536L,48537L,
88761 48538L,48539L,48540L,48541L,48542L,48543L,48544L,48545L,48546L,48547L,
88762 48548L,48549L,48550L,48551L,48552L,48553L,48554L,48555L,48556L,48557L,
88763 48558L,48559L,48560L,48561L,48562L,48563L,48564L,48565L,48566L,48567L,
88764 48568L,48569L,48570L,48571L,48572L,48573L,48574L,48575L,48576L,48577L,
88765 48578L,48579L,48580L,48581L,48582L,48583L,48584L,48585L,48586L,48587L,
88766 48588L,48589L,48590L,48591L,48592L,48593L,48594L,48595L,48596L,48597L,
88767 48598L,48599L,48600L,48601L,48602L,48603L,48604L,48605L,48606L,48607L,
88768 48608L,48609L,48610L,48611L,48612L,48613L,48614L,48615L,48616L,48617L,
88769 48618L,48619L,48620L,48621L,48622L,48623L,48624L,48625L,48626L,48627L,
88770 48628L,48629L,48630L,48631L,48632L,48633L,48634L,48635L,48636L,48637L,
88771 48638L,48639L,48640L,48641L,48642L,48643L,48644L,48645L,48646L,48647L,
88772 48648L,48649L,48650L,48651L,48652L,48653L,48654L,48655L,48656L,48657L,
88773 48658L,48659L,48660L,48661L,48662L,48663L,48664L,48665L,48666L,48667L,
88774 48668L,48669L,48670L,48671L,48672L,48673L,48674L,48675L,48676L,48677L,
88775 48678L,48679L,48680L,48681L,48682L,48683L,48684L,48685L,48686L,48687L,
88776 48688L,48689L,48690L,48691L,48692L,48693L,48694L,48695L,48696L,48697L,
88777 48698L,48699L,48700L,48701L,48702L,48703L,48704L,48705L,48706L,48707L,
88778 48708L,48709L,48710L,48711L,48712L,48713L,48714L,48715L,48716L,48717L,
88779 48718L,48719L,48720L,48721L,48722L,48723L,48724L,48725L,48726L,48727L,
88780 48728L,48729L,48730L,48731L,48732L,48733L,48734L,48735L,48736L,48737L,
88781 48738L,48739L,48740L,48741L,48742L,48743L,48744L,48745L,48746L,48747L,
88782 48748L,48749L,48750L,48751L,48752L,48753L,48754L,48755L,48756L,48757L,
88783 48758L,48759L,48760L,48761L,48762L,48763L,48764L,48765L,48766L,48767L,
88784 48768L,48769L,48770L,48771L,48772L,48773L,48774L,48775L,48776L,48777L,
88785 48778L,48779L,48780L,48781L,48782L,48783L,48784L,48785L,48786L,48787L,
88786 48788L,48789L,48790L,48791L,48792L,48793L,48794L,48795L,48796L,48797L,
88787 48798L,48799L,48800L,48801L,48802L,48803L,48804L,48805L,48806L,48807L,
88788 48808L,48809L,48810L,48811L,48812L,48813L,48814L,48815L,48816L,48817L,
88789 48818L,48819L,48820L,48821L,48822L,48823L,48824L,48825L,48826L,48827L,
88790 48828L,48829L,48830L,48831L,48832L,48833L,48834L,48835L,48836L,48837L,
88791 48838L,48839L,48840L,48841L,48842L,48843L,48844L,48845L,48846L,48847L,
88792 48848L,48849L,48850L,48851L,48852L,48853L,48854L,48855L,48856L,48857L,
88793 48858L,48859L,48860L,48861L,48862L,48863L,48864L,48865L,48866L,48867L,
88794 48868L,48869L,48870L,48871L,48872L,48873L,48874L,48875L,48876L,48877L,
88795 48878L,48879L,48880L,48881L,48882L,48883L,48884L,48885L,48886L,48887L,
88796 48888L,48889L,48890L,48891L,48892L,48893L,48894L,48895L,48896L,48897L,
88797 48898L,48899L,48900L,48901L,48902L,48903L,48904L,48905L,48906L,48907L,
88798 48908L,48909L,48910L,48911L,48912L,48913L,48914L,48915L,48916L,48917L,
88799 48918L,48919L,48920L,48921L,48922L,48923L,48924L,48925L,48926L,48927L,
88800 48928L,48929L,48930L,48931L,48932L,48933L,48934L,48935L,48936L,48937L,
88801 48938L,48939L,48940L,48941L,48942L,48943L,48944L,48945L,48946L,48947L,
88802 48948L,48949L,48950L,48951L,48952L,48953L,48954L,48955L,48956L,48957L,
88803 48958L,48959L,48960L,48961L,48962L,48963L,48964L,48965L,48966L,48967L,
88804 48968L,48969L,48970L,48971L,48972L,48973L,48974L,48975L,48976L,48977L,
88805 48978L,48979L,48980L,48981L,48982L,48983L,48984L,48985L,48986L,48987L,
88806 48988L,48989L,48990L,48991L,48992L,48993L,48994L,48995L,48996L,48997L,
88807 48998L,48999L,49000L,49001L,49002L,49003L,49004L,49005L,49006L,49007L,
88808 49008L,49009L,49010L,49011L,49012L,49013L,49014L,49015L,49016L,49017L,
88809 49018L,49019L,49020L,49021L,49022L,49023L,49024L,49025L,49026L,49027L,
88810 49028L,49029L,49030L,49031L,49032L,49033L,49034L,49035L,49036L,49037L,
88811 49038L,49039L,49040L,49041L,49042L,49043L,49044L,49045L,49046L,49047L,
88812 49048L,49049L,49050L,49051L,49052L,49053L,49054L,49055L,49056L,49057L,
88813 49058L,49059L,49060L,49061L,49062L,49063L,49064L,49065L,49066L,49067L,
88814 49068L,49069L,49070L,49071L,49072L,49073L,49074L,49075L,49076L,49077L,
88815 49078L,49079L,49080L,49081L,49082L,49083L,49084L,49085L,49086L,49087L,
88816 49088L,49089L,49090L,49091L,49092L,49093L,49094L,49095L,49096L,49097L,
88817 49098L,49099L,49100L,49101L,49102L,49103L,49104L,49105L,49106L,49107L,
88818 49108L,49109L,49110L,49111L,49112L,49113L,49114L,49115L,49116L,49117L,
88819 49118L,49119L,49120L,49121L,49122L,49123L,49124L,49125L,49126L,49127L,
88820 49128L,49129L,49130L,49131L,49132L,49133L,49134L,49135L,49136L,49137L,
88821 49138L,49139L,49140L,49141L,49142L,49143L,49144L,49145L,49146L,49147L,
88822 49148L,49149L,49150L,49151L,49152L,49153L,49154L,49155L,49156L,49157L,
88823 49158L,49159L,49160L,49161L,49162L,49163L,49164L,49165L,49166L,49167L,
88824 49168L,49169L,49170L,49171L,49172L,49173L,49174L,49175L,49176L,49177L,
88825 49178L,49179L,49180L,49181L,49182L,49183L,49184L,49185L,49186L,49187L,
88826 49188L,49189L,49190L,49191L,49192L,49193L,49194L,49195L,49196L,49197L,
88827 49198L,49199L,49200L,49201L,49202L,49203L,49204L,49205L,49206L,49207L,
88828 49208L,49209L,49210L,49211L,49212L,49213L,49214L,49215L,49216L,49217L,
88829 49218L,49219L,49220L,49221L,49222L,49223L,49224L,49225L,49226L,49227L,
88830 49228L,49229L,49230L,49231L,49232L,49233L,49234L,49235L,49236L,49237L,
88831 49238L,49239L,49240L,49241L,49242L,49243L,49244L,49245L,49246L,49247L,
88832 49248L,49249L,49250L,49251L,49252L,49253L,49254L,49255L,49256L,49257L,
88833 49258L,49259L,49260L,49261L,49262L,49263L,49264L,49265L,49266L,49267L,
88834 49268L,49269L,49270L,49271L,49272L,49273L,49274L,49275L,49276L,49277L,
88835 49278L,49279L,49280L,49281L,49282L,49283L,49284L,49285L,49286L,49287L,
88836 49288L,49289L,49290L,49291L,49292L,49293L,49294L,49295L,49296L,49297L,
88837 49298L,49299L,49300L,49301L,49302L,49303L,49304L,49305L,49306L,49307L,
88838 49308L,49309L,49310L,49311L,49312L,49313L,49314L,49315L,49316L,49317L,
88839 49318L,49319L,49320L,49321L,49322L,49323L,49324L,49325L,49326L,49327L,
88840 49328L,49329L,49330L,49331L,49332L,49333L,49334L,49335L,49336L,49337L,
88841 49338L,49339L,49340L,49341L,49342L,49343L,49344L,49345L,49346L,49347L,
88842 49348L,49349L,49350L,49351L,49352L,49353L,49354L,49355L,49356L,49357L,
88843 49358L,49359L,49360L,49361L,49362L,49363L,49364L,49365L,49366L,49367L,
88844 49368L,49369L,49370L,49371L,49372L,49373L,49374L,49375L,49376L,49377L,
88845 49378L,49379L,49380L,49381L,49382L,49383L,49384L,49385L,49386L,49387L,
88846 49388L,49389L,49390L,49391L,49392L,49393L,49394L,49395L,49396L,49397L,
88847 49398L,49399L,49400L,49401L,49402L,49403L,49404L,49405L,49406L,49407L,
88848 49408L,49409L,49410L,49411L,49412L,49413L,49414L,49415L,49416L,49417L,
88849 49418L,49419L,49420L,49421L,49422L,49423L,49424L,49425L,49426L,49427L,
88850 49428L,49429L,49430L,49431L,49432L,49433L,49434L,49435L,49436L,49437L,
88851 49438L,49439L,49440L,49441L,49442L,49443L,49444L,49445L,49446L,49447L,
88852 49448L,49449L,49450L,49451L,49452L,49453L,49454L,49455L,49456L,49457L,
88853 49458L,49459L,49460L,49461L,49462L,49463L,49464L,49465L,49466L,49467L,
88854 49468L,49469L,49470L,49471L,49472L,49473L,49474L,49475L,49476L,49477L,
88855 49478L,49479L,49480L,49481L,49482L,49483L,49484L,49485L,49486L,49487L,
88856 49488L,49489L,49490L,49491L,49492L,49493L,49494L,49495L,49496L,49497L,
88857 49498L,49499L,49500L,49501L,49502L,49503L,49504L,49505L,49506L,49507L,
88858 49508L,49509L,49510L,49511L,49512L,49513L,49514L,49515L,49516L,49517L,
88859 49518L,49519L,49520L,49521L,49522L,49523L,49524L,49525L,49526L,49527L,
88860 49528L,49529L,49530L,49531L,49532L,49533L,49534L,49535L,49536L,49537L,
88861 49538L,49539L,49540L,49541L,49542L,49543L,49544L,49545L,49546L,49547L,
88862 49548L,49549L,49550L,49551L,49552L,49553L,49554L,49555L,49556L,49557L,
88863 49558L,49559L,49560L,49561L,49562L,49563L,49564L,49565L,49566L,49567L,
88864 49568L,49569L,49570L,49571L,49572L,49573L,49574L,49575L,49576L,49577L,
88865 49578L,49579L,49580L,49581L,49582L,49583L,49584L,49585L,49586L,49587L,
88866 49588L,49589L,49590L,49591L,49592L,49593L,49594L,49595L,49596L,49597L,
88867 49598L,49599L,49600L,49601L,49602L,49603L,49604L,49605L,49606L,49607L,
88868 49608L,49609L,49610L,49611L,49612L,49613L,49614L,49615L,49616L,49617L,
88869 49618L,49619L,49620L,49621L,49622L,49623L,49624L,49625L,49626L,49627L,
88870 49628L,49629L,49630L,49631L,49632L,49633L,49634L,49635L,49636L,49637L,
88871 49638L,49639L,49640L,49641L,49642L,49643L,49644L,49645L,49646L,49647L,
88872 49648L,49649L,49650L,49651L,49652L,49653L,49654L,49655L,49656L,49657L,
88873 49658L,49659L,49660L,49661L,49662L,49663L,49664L,49665L,49666L,49667L,
88874 49668L,49669L,49670L,49671L,49672L,49673L,49674L,49675L,49676L,49677L,
88875 49678L,49679L,49680L,49681L,49682L,49683L,49684L,49685L,49686L,49687L,
88876 49688L,49689L,49690L,49691L,49692L,49693L,49694L,49695L,49696L,49697L,
88877 49698L,49699L,49700L,49701L,49702L,49703L,49704L,49705L,49706L,49707L,
88878 49708L,49709L,49710L,49711L,49712L,49713L,49714L,49715L,49716L,49717L,
88879 49718L,49719L,49720L,49721L,49722L,49723L,49724L,49725L,49726L,49727L,
88880 49728L,49729L,49730L,49731L,49732L,49733L,49734L,49735L,49736L,49737L,
88881 49738L,49739L,49740L,49741L,49742L,49743L,49744L,49745L,49746L,49747L,
88882 49748L,49749L,49750L,49751L,49752L,49753L,49754L,49755L,49756L,49757L,
88883 49758L,49759L,49760L,49761L,49762L,49763L,49764L,49765L,49766L,49767L,
88884 49768L,49769L,49770L,49771L,49772L,49773L,49774L,49775L,49776L,49777L,
88885 49778L,49779L,49780L,49781L,49782L,49783L,49784L,49785L,49786L,49787L,
88886 49788L,49789L,49790L,49791L,49792L,49793L,49794L,49795L,49796L,49797L,
88887 49798L,49799L,49800L,49801L,49802L,49803L,49804L,49805L,49806L,49807L,
88888 49808L,49809L,49810L,49811L,49812L,49813L,49814L,49815L,49816L,49817L,
88889 49818L,49819L,49820L,49821L,49822L,49823L,49824L,49825L,49826L,49827L,
88890 49828L,49829L,49830L,49831L,49832L,49833L,49834L,49835L,49836L,49837L,
88891 49838L,49839L,49840L,49841L,49842L,49843L,49844L,49845L,49846L,49847L,
88892 49848L,49849L,49850L,49851L,49852L,49853L,49854L,49855L,49856L,49857L,
88893 49858L,49859L,49860L,49861L,49862L,49863L,49864L,49865L,49866L,49867L,
88894 49868L,49869L,49870L,49871L,49872L,49873L,49874L,49875L,49876L,49877L,
88895 49878L,49879L,49880L,49881L,49882L,49883L,49884L,49885L,49886L,49887L,
88896 49888L,49889L,49890L,49891L,49892L,49893L,49894L,49895L,49896L,49897L,
88897 49898L,49899L,49900L,49901L,49902L,49903L,49904L,49905L,49906L,49907L,
88898 49908L,49909L,49910L,49911L,49912L,49913L,49914L,49915L,49916L,49917L,
88899 49918L,49919L,49920L,49921L,49922L,49923L,49924L,49925L,49926L,49927L,
88900 49928L,49929L,49930L,49931L,49932L,49933L,49934L,49935L,49936L,49937L,
88901 49938L,49939L,49940L,49941L,49942L,49943L,49944L,49945L,49946L,49947L,
88902 49948L,49949L,49950L,49951L,49952L,49953L,49954L,49955L,49956L,49957L,
88903 49958L,49959L,49960L,49961L,49962L,49963L,49964L,49965L,49966L,49967L,
88904 49968L,49969L,49970L,49971L,49972L,49973L,49974L,49975L,49976L,49977L,
88905 49978L,49979L,49980L,49981L,49982L,49983L,49984L,49985L,49986L,49987L,
88906 49988L,49989L,49990L,49991L,49992L,49993L,49994L,49995L,49996L,49997L,
88907 49998L,49999L,50000L,50001L,50002L,50003L,50004L,50005L,50006L,50007L,
88908 50008L,50009L,50010L,50011L,50012L,50013L,50014L,50015L,50016L,50017L,
88909 50018L,50019L,50020L,50021L,50022L,50023L,50024L,50025L,50026L,50027L,
88910 50028L,50029L,50030L,50031L,50032L,50033L,50034L,50035L,50036L,50037L,
88911 50038L,50039L,50040L,50041L,50042L,50043L,50044L,50045L,50046L,50047L,
88912 50048L,50049L,50050L,50051L,50052L,50053L,50054L,50055L,50056L,50057L,
88913 50058L,50059L,50060L,50061L,50062L,50063L,50064L,50065L,50066L,50067L,
88914 50068L,50069L,50070L,50071L,50072L,50073L,50074L,50075L,50076L,50077L,
88915 50078L,50079L,50080L,50081L,50082L,50083L,50084L,50085L,50086L,50087L,
88916 50088L,50089L,50090L,50091L,50092L,50093L,50094L,50095L,50096L,50097L,
88917 50098L,50099L,50100L,50101L,50102L,50103L,50104L,50105L,50106L,50107L,
88918 50108L,50109L,50110L,50111L,50112L,50113L,50114L,50115L,50116L,50117L,
88919 50118L,50119L,50120L,50121L,50122L,50123L,50124L,50125L,50126L,50127L,
88920 50128L,50129L,50130L,50131L,50132L,50133L,50134L,50135L,50136L,50137L,
88921 50138L,50139L,50140L,50141L,50142L,50143L,50144L,50145L,50146L,50147L,
88922 50148L,50149L,50150L,50151L,50152L,50153L,50154L,50155L,50156L,50157L,
88923 50158L,50159L,50160L,50161L,50162L,50163L,50164L,50165L,50166L,50167L,
88924 50168L,50169L,50170L,50171L,50172L,50173L,50174L,50175L,50176L,50177L,
88925 50178L,50179L,50180L,50181L,50182L,50183L,50184L,50185L,50186L,50187L,
88926 50188L,50189L,50190L,50191L,50192L,50193L,50194L,50195L,50196L,50197L,
88927 50198L,50199L,50200L,50201L,50202L,50203L,50204L,50205L,50206L,50207L,
88928 50208L,50209L,50210L,50211L,50212L,50213L,50214L,50215L,50216L,50217L,
88929 50218L,50219L,50220L,50221L,50222L,50223L,50224L,50225L,50226L,50227L,
88930 50228L,50229L,50230L,50231L,50232L,50233L,50234L,50235L,50236L,50237L,
88931 50238L,50239L,50240L,50241L,50242L,50243L,50244L,50245L,50246L,50247L,
88932 50248L,50249L,50250L,50251L,50252L,50253L,50254L,50255L,50256L,50257L,
88933 50258L,50259L,50260L,50261L,50262L,50263L,50264L,50265L,50266L,50267L,
88934 50268L,50269L,50270L,50271L,50272L,50273L,50274L,50275L,50276L,50277L,
88935 50278L,50279L,50280L,50281L,50282L,50283L,50284L,50285L,50286L,50287L,
88936 50288L,50289L,50290L,50291L,50292L,50293L,50294L,50295L,50296L,50297L,
88937 50298L,50299L,50300L,50301L,50302L,50303L,50304L,50305L,50306L,50307L,
88938 50308L,50309L,50310L,50311L,50312L,50313L,50314L,50315L,50316L,50317L,
88939 50318L,50319L,50320L,50321L,50322L,50323L,50324L,50325L,50326L,50327L,
88940 50328L,50329L,50330L,50331L,50332L,50333L,50334L,50335L,50336L,50337L,
88941 50338L,50339L,50340L,50341L,50342L,50343L,50344L,50345L,50346L,50347L,
88942 50348L,50349L,50350L,50351L,50352L,50353L,50354L,50355L,50356L,50357L,
88943 50358L,50359L,50360L,50361L,50362L,50363L,50364L,50365L,50366L,50367L,
88944 50368L,50369L,50370L,50371L,50372L,50373L,50374L,50375L,50376L,50377L,
88945 50378L,50379L,50380L,50381L,50382L,50383L,50384L,50385L,50386L,50387L,
88946 50388L,50389L,50390L,50391L,50392L,50393L,50394L,50395L,50396L,50397L,
88947 50398L,50399L,50400L,50401L,50402L,50403L,50404L,50405L,50406L,50407L,
88948 50408L,50409L,50410L,50411L,50412L,50413L,50414L,50415L,50416L,50417L,
88949 50418L,50419L,50420L,50421L,50422L,50423L,50424L,50425L,50426L,50427L,
88950 50428L,50429L,50430L,50431L,50432L,50433L,50434L,50435L,50436L,50437L,
88951 50438L,50439L,50440L,50441L,50442L,50443L,50444L,50445L,50446L,50447L,
88952 50448L,50449L,50450L,50451L,50452L,50453L,50454L,50455L,50456L,50457L,
88953 50458L,50459L,50460L,50461L,50462L,50463L,50464L,50465L,50466L,50467L,
88954 50468L,50469L,50470L,50471L,50472L,50473L,50474L,50475L,50476L,50477L,
88955 50478L,50479L,50480L,50481L,50482L,50483L,50484L,50485L,50486L,50487L,
88956 50488L,50489L,50490L,50491L,50492L,50493L,50494L,50495L,50496L,50497L,
88957 50498L,50499L,50500L,50501L,50502L,50503L,50504L,50505L,50506L,50507L,
88958 50508L,50509L,50510L,50511L,50512L,50513L,50514L,50515L,50516L,50517L,
88959 50518L,50519L,50520L,50521L,50522L,50523L,50524L,50525L,50526L,50527L,
88960 50528L,50529L,50530L,50531L,50532L,50533L,50534L,50535L,50536L,50537L,
88961 50538L,50539L,50540L,50541L,50542L,50543L,50544L,50545L,50546L,50547L,
88962 50548L,50549L,50550L,50551L,50552L,50553L,50554L,50555L,50556L,50557L,
88963 50558L,50559L,50560L,50561L,50562L,50563L,50564L,50565L,50566L,50567L,
88964 50568L,50569L,50570L,50571L,50572L,50573L,50574L,50575L,50576L,50577L,
88965 50578L,50579L,50580L,50581L,50582L,50583L,50584L,50585L,50586L,50587L,
88966 50588L,50589L,50590L,50591L,50592L,50593L,50594L,50595L,50596L,50597L,
88967 50598L,50599L,50600L,50601L,50602L,50603L,50604L,50605L,50606L,50607L,
88968 50608L,50609L,50610L,50611L,50612L,50613L,50614L,50615L,50616L,50617L,
88969 50618L,50619L,50620L,50621L,50622L,50623L,50624L,50625L,50626L,50627L,
88970 50628L,50629L,50630L,50631L,50632L,50633L,50634L,50635L,50636L,50637L,
88971 50638L,50639L,50640L,50641L,50642L,50643L,50644L,50645L,50646L,50647L,
88972 50648L,50649L,50650L,50651L,50652L,50653L,50654L,50655L,50656L,50657L,
88973 50658L,50659L,50660L,50661L,50662L,50663L,50664L,50665L,50666L,50667L,
88974 50668L,50669L,50670L,50671L,50672L,50673L,50674L,50675L,50676L,50677L,
88975 50678L,50679L,50680L,50681L,50682L,50683L,50684L,50685L,50686L,50687L,
88976 50688L,50689L,50690L,50691L,50692L,50693L,50694L,50695L,50696L,50697L,
88977 50698L,50699L,50700L,50701L,50702L,50703L,50704L,50705L,50706L,50707L,
88978 50708L,50709L,50710L,50711L,50712L,50713L,50714L,50715L,50716L,50717L,
88979 50718L,50719L,50720L,50721L,50722L,50723L,50724L,50725L,50726L,50727L,
88980 50728L,50729L,50730L,50731L,50732L,50733L,50734L,50735L,50736L,50737L,
88981 50738L,50739L,50740L,50741L,50742L,50743L,50744L,50745L,50746L,50747L,
88982 50748L,50749L,50750L,50751L,50752L,50753L,50754L,50755L,50756L,50757L,
88983 50758L,50759L,50760L,50761L,50762L,50763L,50764L,50765L,50766L,50767L,
88984 50768L,50769L,50770L,50771L,50772L,50773L,50774L,50775L,50776L,50777L,
88985 50778L,50779L,50780L,50781L,50782L,50783L,50784L,50785L,50786L,50787L,
88986 50788L,50789L,50790L,50791L,50792L,50793L,50794L,50795L,50796L,50797L,
88987 50798L,50799L,50800L,50801L,50802L,50803L,50804L,50805L,50806L,50807L,
88988 50808L,50809L,50810L,50811L,50812L,50813L,50814L,50815L,50816L,50817L,
88989 50818L,50819L,50820L,50821L,50822L,50823L,50824L,50825L,50826L,50827L,
88990 50828L,50829L,50830L,50831L,50832L,50833L,50834L,50835L,50836L,50837L,
88991 50838L,50839L,50840L,50841L,50842L,50843L,50844L,50845L,50846L,50847L,
88992 50848L,50849L,50850L,50851L,50852L,50853L,50854L,50855L,50856L,50857L,
88993 50858L,50859L,50860L,50861L,50862L,50863L,50864L,50865L,50866L,50867L,
88994 50868L,50869L,50870L,50871L,50872L,50873L,50874L,50875L,50876L,50877L,
88995 50878L,50879L,50880L,50881L,50882L,50883L,50884L,50885L,50886L,50887L,
88996 50888L,50889L,50890L,50891L,50892L,50893L,50894L,50895L,50896L,50897L,
88997 50898L,50899L,50900L,50901L,50902L,50903L,50904L,50905L,50906L,50907L,
88998 50908L,50909L,50910L,50911L,50912L,50913L,50914L,50915L,50916L,50917L,
88999 50918L,50919L,50920L,50921L,50922L,50923L,50924L,50925L,50926L,50927L,
89000 50928L,50929L,50930L,50931L,50932L,50933L,50934L,50935L,50936L,50937L,
89001 50938L,50939L,50940L,50941L,50942L,50943L,50944L,50945L,50946L,50947L,
89002 50948L,50949L,50950L,50951L,50952L,50953L,50954L,50955L,50956L,50957L,
89003 50958L,50959L,50960L,50961L,50962L,50963L,50964L,50965L,50966L,50967L,
89004 50968L,50969L,50970L,50971L,50972L,50973L,50974L,50975L,50976L,50977L,
89005 50978L,50979L,50980L,50981L,50982L,50983L,50984L,50985L,50986L,50987L,
89006 50988L,50989L,50990L,50991L,50992L,50993L,50994L,50995L,50996L,50997L,
89007 50998L,50999L,51000L,51001L,51002L,51003L,51004L,51005L,51006L,51007L,
89008 51008L,51009L,51010L,51011L,51012L,51013L,51014L,51015L,51016L,51017L,
89009 51018L,51019L,51020L,51021L,51022L,51023L,51024L,51025L,51026L,51027L,
89010 51028L,51029L,51030L,51031L,51032L,51033L,51034L,51035L,51036L,51037L,
89011 51038L,51039L,51040L,51041L,51042L,51043L,51044L,51045L,51046L,51047L,
89012 51048L,51049L,51050L,51051L,51052L,51053L,51054L,51055L,51056L,51057L,
89013 51058L,51059L,51060L,51061L,51062L,51063L,51064L,51065L,51066L,51067L,
89014 51068L,51069L,51070L,51071L,51072L,51073L,51074L,51075L,51076L,51077L,
89015 51078L,51079L,51080L,51081L,51082L,51083L,51084L,51085L,51086L,51087L,
89016 51088L,51089L,51090L,51091L,51092L,51093L,51094L,51095L,51096L,51097L,
89017 51098L,51099L,51100L,51101L,51102L,51103L,51104L,51105L,51106L,51107L,
89018 51108L,51109L,51110L,51111L,51112L,51113L,51114L,51115L,51116L,51117L,
89019 51118L,51119L,51120L,51121L,51122L,51123L,51124L,51125L,51126L,51127L,
89020 51128L,51129L,51130L,51131L,51132L,51133L,51134L,51135L,51136L,51137L,
89021 51138L,51139L,51140L,51141L,51142L,51143L,51144L,51145L,51146L,51147L,
89022 51148L,51149L,51150L,51151L,51152L,51153L,51154L,51155L,51156L,51157L,
89023 51158L,51159L,51160L,51161L,51162L,51163L,51164L,51165L,51166L,51167L,
89024 51168L,51169L,51170L,51171L,51172L,51173L,51174L,51175L,51176L,51177L,
89025 51178L,51179L,51180L,51181L,51182L,51183L,51184L,51185L,51186L,51187L,
89026 51188L,51189L,51190L,51191L,51192L,51193L,51194L,51195L,51196L,51197L,
89027 51198L,51199L,51200L,51201L,51202L,51203L,51204L,51205L,51206L,51207L,
89028 51208L,51209L,51210L,51211L,51212L,51213L,51214L,51215L,51216L,51217L,
89029 51218L,51219L,51220L,51221L,51222L,51223L,51224L,51225L,51226L,51227L,
89030 51228L,51229L,51230L,51231L,51232L,51233L,51234L,51235L,51236L,51237L,
89031 51238L,51239L,51240L,51241L,51242L,51243L,51244L,51245L,51246L,51247L,
89032 51248L,51249L,51250L,51251L,51252L,51253L,51254L,51255L,51256L,51257L,
89033 51258L,51259L,51260L,51261L,51262L,51263L,51264L,51265L,51266L,51267L,
89034 51268L,51269L,51270L,51271L,51272L,51273L,51274L,51275L,51276L,51277L,
89035 51278L,51279L,51280L,51281L,51282L,51283L,51284L,51285L,51286L,51287L,
89036 51288L,51289L,51290L,51291L,51292L,51293L,51294L,51295L,51296L,51297L,
89037 51298L,51299L,51300L,51301L,51302L,51303L,51304L,51305L,51306L,51307L,
89038 51308L,51309L,51310L,51311L,51312L,51313L,51314L,51315L,51316L,51317L,
89039 51318L,51319L,51320L,51321L,51322L,51323L,51324L,51325L,51326L,51327L,
89040 51328L,51329L,51330L,51331L,51332L,51333L,51334L,51335L,51336L,51337L,
89041 51338L,51339L,51340L,51341L,51342L,51343L,51344L,51345L,51346L,51347L,
89042 51348L,51349L,51350L,51351L,51352L,51353L,51354L,51355L,51356L,51357L,
89043 51358L,51359L,51360L,51361L,51362L,51363L,51364L,51365L,51366L,51367L,
89044 51368L,51369L,51370L,51371L,51372L,51373L,51374L,51375L,51376L,51377L,
89045 51378L,51379L,51380L,51381L,51382L,51383L,51384L,51385L,51386L,51387L,
89046 51388L,51389L,51390L,51391L,51392L,51393L,51394L,51395L,51396L,51397L,
89047 51398L,51399L,51400L,51401L,51402L,51403L,51404L,51405L,51406L,51407L,
89048 51408L,51409L,51410L,51411L,51412L,51413L,51414L,51415L,51416L,51417L,
89049 51418L,51419L,51420L,51421L,51422L,51423L,51424L,51425L,51426L,51427L,
89050 51428L,51429L,51430L,51431L,51432L,51433L,51434L,51435L,51436L,51437L,
89051 51438L,51439L,51440L,51441L,51442L,51443L,51444L,51445L,51446L,51447L,
89052 51448L,51449L,51450L,51451L,51452L,51453L,51454L,51455L,51456L,51457L,
89053 51458L,51459L,51460L,51461L,51462L,51463L,51464L,51465L,51466L,51467L,
89054 51468L,51469L,51470L,51471L,51472L,51473L,51474L,51475L,51476L,51477L,
89055 51478L,51479L,51480L,51481L,51482L,51483L,51484L,51485L,51486L,51487L,
89056 51488L,51489L,51490L,51491L,51492L,51493L,51494L,51495L,51496L,51497L,
89057 51498L,51499L,51500L,51501L,51502L,51503L,51504L,51505L,51506L,51507L,
89058 51508L,51509L,51510L,51511L,51512L,51513L,51514L,51515L,51516L,51517L,
89059 51518L,51519L,51520L,51521L,51522L,51523L,51524L,51525L,51526L,51527L,
89060 51528L,51529L,51530L,51531L,51532L,51533L,51534L,51535L,51536L,51537L,
89061 51538L,51539L,51540L,51541L,51542L,51543L,51544L,51545L,51546L,51547L,
89062 51548L,51549L,51550L,51551L,51552L,51553L,51554L,51555L,51556L,51557L,
89063 51558L,51559L,51560L,51561L,51562L,51563L,51564L,51565L,51566L,51567L,
89064 51568L,51569L,51570L,51571L,51572L,51573L,51574L,51575L,51576L,51577L,
89065 51578L,51579L,51580L,51581L,51582L,51583L,51584L,51585L,51586L,51587L,
89066 51588L,51589L,51590L,51591L,51592L,51593L,51594L,51595L,51596L,51597L,
89067 51598L,51599L,51600L,51601L,51602L,51603L,51604L,51605L,51606L,51607L,
89068 51608L,51609L,51610L,51611L,51612L,51613L,51614L,51615L,51616L,51617L,
89069 51618L,51619L,51620L,51621L,51622L,51623L,51624L,51625L,51626L,51627L,
89070 51628L,51629L,51630L,51631L,51632L,51633L,51634L,51635L,51636L,51637L,
89071 51638L,51639L,51640L,51641L,51642L,51643L,51644L,51645L,51646L,51647L,
89072 51648L,51649L,51650L,51651L,51652L,51653L,51654L,51655L,51656L,51657L,
89073 51658L,51659L,51660L,51661L,51662L,51663L,51664L,51665L,51666L,51667L,
89074 51668L,51669L,51670L,51671L,51672L,51673L,51674L,51675L,51676L,51677L,
89075 51678L,51679L,51680L,51681L,51682L,51683L,51684L,51685L,51686L,51687L,
89076 51688L,51689L,51690L,51691L,51692L,51693L,51694L,51695L,51696L,51697L,
89077 51698L,51699L,51700L,51701L,51702L,51703L,51704L,51705L,51706L,51707L,
89078 51708L,51709L,51710L,51711L,51712L,51713L,51714L,51715L,51716L,51717L,
89079 51718L,51719L,51720L,51721L,51722L,51723L,51724L,51725L,51726L,51727L,
89080 51728L,51729L,51730L,51731L,51732L,51733L,51734L,51735L,51736L,51737L,
89081 51738L,51739L,51740L,51741L,51742L,51743L,51744L,51745L,51746L,51747L,
89082 51748L,51749L,51750L,51751L,51752L,51753L,51754L,51755L,51756L,51757L,
89083 51758L,51759L,51760L,51761L,51762L,51763L,51764L,51765L,51766L,51767L,
89084 51768L,51769L,51770L,51771L,51772L,51773L,51774L,51775L,51776L,51777L,
89085 51778L,51779L,51780L,51781L,51782L,51783L,51784L,51785L,51786L,51787L,
89086 51788L,51789L,51790L,51791L,51792L,51793L,51794L,51795L,51796L,51797L,
89087 51798L,51799L,51800L,51801L,51802L,51803L,51804L,51805L,51806L,51807L,
89088 51808L,51809L,51810L,51811L,51812L,51813L,51814L,51815L,51816L,51817L,
89089 51818L,51819L,51820L,51821L,51822L,51823L,51824L,51825L,51826L,51827L,
89090 51828L,51829L,51830L,51831L,51832L,51833L,51834L,51835L,51836L,51837L,
89091 51838L,51839L,51840L,51841L,51842L,51843L,51844L,51845L,51846L,51847L,
89092 51848L,51849L,51850L,51851L,51852L,51853L,51854L,51855L,51856L,51857L,
89093 51858L,51859L,51860L,51861L,51862L,51863L,51864L,51865L,51866L,51867L,
89094 51868L,51869L,51870L,51871L,51872L,51873L,51874L,51875L,51876L,51877L,
89095 51878L,51879L,51880L,51881L,51882L,51883L,51884L,51885L,51886L,51887L,
89096 51888L,51889L,51890L,51891L,51892L,51893L,51894L,51895L,51896L,51897L,
89097 51898L,51899L,51900L,51901L,51902L,51903L,51904L,51905L,51906L,51907L,
89098 51908L,51909L,51910L,51911L,51912L,51913L,51914L,51915L,51916L,51917L,
89099 51918L,51919L,51920L,51921L,51922L,51923L,51924L,51925L,51926L,51927L,
89100 51928L,51929L,51930L,51931L,51932L,51933L,51934L,51935L,51936L,51937L,
89101 51938L,51939L,51940L,51941L,51942L,51943L,51944L,51945L,51946L,51947L,
89102 51948L,51949L,51950L,51951L,51952L,51953L,51954L,51955L,51956L,51957L,
89103 51958L,51959L,51960L,51961L,51962L,51963L,51964L,51965L,51966L,51967L,
89104 51968L,51969L,51970L,51971L,51972L,51973L,51974L,51975L,51976L,51977L,
89105 51978L,51979L,51980L,51981L,51982L,51983L,51984L,51985L,51986L,51987L,
89106 51988L,51989L,51990L,51991L,51992L,51993L,51994L,51995L,51996L,51997L,
89107 51998L,51999L,52000L,52001L,52002L,52003L,52004L,52005L,52006L,52007L,
89108 52008L,52009L,52010L,52011L,52012L,52013L,52014L,52015L,52016L,52017L,
89109 52018L,52019L,52020L,52021L,52022L,52023L,52024L,52025L,52026L,52027L,
89110 52028L,52029L,52030L,52031L,52032L,52033L,52034L,52035L,52036L,52037L,
89111 52038L,52039L,52040L,52041L,52042L,52043L,52044L,52045L,52046L,52047L,
89112 52048L,52049L,52050L,52051L,52052L,52053L,52054L,52055L,52056L,52057L,
89113 52058L,52059L,52060L,52061L,52062L,52063L,52064L,52065L,52066L,52067L,
89114 52068L,52069L,52070L,52071L,52072L,52073L,52074L,52075L,52076L,52077L,
89115 52078L,52079L,52080L,52081L,52082L,52083L,52084L,52085L,52086L,52087L,
89116 52088L,52089L,52090L,52091L,52092L,52093L,52094L,52095L,52096L,52097L,
89117 52098L,52099L,52100L,52101L,52102L,52103L,52104L,52105L,52106L,52107L,
89118 52108L,52109L,52110L,52111L,52112L,52113L,52114L,52115L,52116L,52117L,
89119 52118L,52119L,52120L,52121L,52122L,52123L,52124L,52125L,52126L,52127L,
89120 52128L,52129L,52130L,52131L,52132L,52133L,52134L,52135L,52136L,52137L,
89121 52138L,52139L,52140L,52141L,52142L,52143L,52144L,52145L,52146L,52147L,
89122 52148L,52149L,52150L,52151L,52152L,52153L,52154L,52155L,52156L,52157L,
89123 52158L,52159L,52160L,52161L,52162L,52163L,52164L,52165L,52166L,52167L,
89124 52168L,52169L,52170L,52171L,52172L,52173L,52174L,52175L,52176L,52177L,
89125 52178L,52179L,52180L,52181L,52182L,52183L,52184L,52185L,52186L,52187L,
89126 52188L,52189L,52190L,52191L,52192L,52193L,52194L,52195L,52196L,52197L,
89127 52198L,52199L,52200L,52201L,52202L,52203L,52204L,52205L,52206L,52207L,
89128 52208L,52209L,52210L,52211L,52212L,52213L,52214L,52215L,52216L,52217L,
89129 52218L,52219L,52220L,52221L,52222L,52223L,52224L,52225L,52226L,52227L,
89130 52228L,52229L,52230L,52231L,52232L,52233L,52234L,52235L,52236L,52237L,
89131 52238L,52239L,52240L,52241L,52242L,52243L,52244L,52245L,52246L,52247L,
89132 52248L,52249L,52250L,52251L,52252L,52253L,52254L,52255L,52256L,52257L,
89133 52258L,52259L,52260L,52261L,52262L,52263L,52264L,52265L,52266L,52267L,
89134 52268L,52269L,52270L,52271L,52272L,52273L,52274L,52275L,52276L,52277L,
89135 52278L,52279L,52280L,52281L,52282L,52283L,52284L,52285L,52286L,52287L,
89136 52288L,52289L,52290L,52291L,52292L,52293L,52294L,52295L,52296L,52297L,
89137 52298L,52299L,52300L,52301L,52302L,52303L,52304L,52305L,52306L,52307L,
89138 52308L,52309L,52310L,52311L,52312L,52313L,52314L,52315L,52316L,52317L,
89139 52318L,52319L,52320L,52321L,52322L,52323L,52324L,52325L,52326L,52327L,
89140 52328L,52329L,52330L,52331L,52332L,52333L,52334L,52335L,52336L,52337L,
89141 52338L,52339L,52340L,52341L,52342L,52343L,52344L,52345L,52346L,52347L,
89142 52348L,52349L,52350L,52351L,52352L,52353L,52354L,52355L,52356L,52357L,
89143 52358L,52359L,52360L,52361L,52362L,52363L,52364L,52365L,52366L,52367L,
89144 52368L,52369L,52370L,52371L,52372L,52373L,52374L,52375L,52376L,52377L,
89145 52378L,52379L,52380L,52381L,52382L,52383L,52384L,52385L,52386L,52387L,
89146 52388L,52389L,52390L,52391L,52392L,52393L,52394L,52395L,52396L,52397L,
89147 52398L,52399L,52400L,52401L,52402L,52403L,52404L,52405L,52406L,52407L,
89148 52408L,52409L,52410L,52411L,52412L,52413L,52414L,52415L,52416L,52417L,
89149 52418L,52419L,52420L,52421L,52422L,52423L,52424L,52425L,52426L,52427L,
89150 52428L,52429L,52430L,52431L,52432L,52433L,52434L,52435L,52436L,52437L,
89151 52438L,52439L,52440L,52441L,52442L,52443L,52444L,52445L,52446L,52447L,
89152 52448L,52449L,52450L,52451L,52452L,52453L,52454L,52455L,52456L,52457L,
89153 52458L,52459L,52460L,52461L,52462L,52463L,52464L,52465L,52466L,52467L,
89154 52468L,52469L,52470L,52471L,52472L,52473L,52474L,52475L,52476L,52477L,
89155 52478L,52479L,52480L,52481L,52482L,52483L,52484L,52485L,52486L,52487L,
89156 52488L,52489L,52490L,52491L,52492L,52493L,52494L,52495L,52496L,52497L,
89157 52498L,52499L,52500L,52501L,52502L,52503L,52504L,52505L,52506L,52507L,
89158 52508L,52509L,52510L,52511L,52512L,52513L,52514L,52515L,52516L,52517L,
89159 52518L,52519L,52520L,52521L,52522L,52523L,52524L,52525L,52526L,52527L,
89160 52528L,52529L,52530L,52531L,52532L,52533L,52534L,52535L,52536L,52537L,
89161 52538L,52539L,52540L,52541L,52542L,52543L,52544L,52545L,52546L,52547L,
89162 52548L,52549L,52550L,52551L,52552L,52553L,52554L,52555L,52556L,52557L,
89163 52558L,52559L,52560L,52561L,52562L,52563L,52564L,52565L,52566L,52567L,
89164 52568L,52569L,52570L,52571L,52572L,52573L,52574L,52575L,52576L,52577L,
89165 52578L,52579L,52580L,52581L,52582L,52583L,52584L,52585L,52586L,52587L,
89166 52588L,52589L,52590L,52591L,52592L,52593L,52594L,52595L,52596L,52597L,
89167 52598L,52599L,52600L,52601L,52602L,52603L,52604L,52605L,52606L,52607L,
89168 52608L,52609L,52610L,52611L,52612L,52613L,52614L,52615L,52616L,52617L,
89169 52618L,52619L,52620L,52621L,52622L,52623L,52624L,52625L,52626L,52627L,
89170 52628L,52629L,52630L,52631L,52632L,52633L,52634L,52635L,52636L,52637L,
89171 52638L,52639L,52640L,52641L,52642L,52643L,52644L,52645L,52646L,52647L,
89172 52648L,52649L,52650L,52651L,52652L,52653L,52654L,52655L,52656L,52657L,
89173 52658L,52659L,52660L,52661L,52662L,52663L,52664L,52665L,52666L,52667L,
89174 52668L,52669L,52670L,52671L,52672L,52673L,52674L,52675L,52676L,52677L,
89175 52678L,52679L,52680L,52681L,52682L,52683L,52684L,52685L,52686L,52687L,
89176 52688L,52689L,52690L,52691L,52692L,52693L,52694L,52695L,52696L,52697L,
89177 52698L,52699L,52700L,52701L,52702L,52703L,52704L,52705L,52706L,52707L,
89178 52708L,52709L,52710L,52711L,52712L,52713L,52714L,52715L,52716L,52717L,
89179 52718L,52719L,52720L,52721L,52722L,52723L,52724L,52725L,52726L,52727L,
89180 52728L,52729L,52730L,52731L,52732L,52733L,52734L,52735L,52736L,52737L,
89181 52738L,52739L,52740L,52741L,52742L,52743L,52744L,52745L,52746L,52747L,
89182 52748L,52749L,52750L,52751L,52752L,52753L,52754L,52755L,52756L,52757L,
89183 52758L,52759L,52760L,52761L,52762L,52763L,52764L,52765L,52766L,52767L,
89184 52768L,52769L,52770L,52771L,52772L,52773L,52774L,52775L,52776L,52777L,
89185 52778L,52779L,52780L,52781L,52782L,52783L,52784L,52785L,52786L,52787L,
89186 52788L,52789L,52790L,52791L,52792L,52793L,52794L,52795L,52796L,52797L,
89187 52798L,52799L,52800L,52801L,52802L,52803L,52804L,52805L,52806L,52807L,
89188 52808L,52809L,52810L,52811L,52812L,52813L,52814L,52815L,52816L,52817L,
89189 52818L,52819L,52820L,52821L,52822L,52823L,52824L,52825L,52826L,52827L,
89190 52828L,52829L,52830L,52831L,52832L,52833L,52834L,52835L,52836L,52837L,
89191 52838L,52839L,52840L,52841L,52842L,52843L,52844L,52845L,52846L,52847L,
89192 52848L,52849L,52850L,52851L,52852L,52853L,52854L,52855L,52856L,52857L,
89193 52858L,52859L,52860L,52861L,52862L,52863L,52864L,52865L,52866L,52867L,
89194 52868L,52869L,52870L,52871L,52872L,52873L,52874L,52875L,52876L,52877L,
89195 52878L,52879L,52880L,52881L,52882L,52883L,52884L,52885L,52886L,52887L,
89196 52888L,52889L,52890L,52891L,52892L,52893L,52894L,52895L,52896L,52897L,
89197 52898L,52899L,52900L,52901L,52902L,52903L,52904L,52905L,52906L,52907L,
89198 52908L,52909L,52910L,52911L,52912L,52913L,52914L,52915L,52916L,52917L,
89199 52918L,52919L,52920L,52921L,52922L,52923L,52924L,52925L,52926L,52927L,
89200 52928L,52929L,52930L,52931L,52932L,52933L,52934L,52935L,52936L,52937L,
89201 52938L,52939L,52940L,52941L,52942L,52943L,52944L,52945L,52946L,52947L,
89202 52948L,52949L,52950L,52951L,52952L,52953L,52954L,52955L,52956L,52957L,
89203 52958L,52959L,52960L,52961L,52962L,52963L,52964L,52965L,52966L,52967L,
89204 52968L,52969L,52970L,52971L,52972L,52973L,52974L,52975L,52976L,52977L,
89205 52978L,52979L,52980L,52981L,52982L,52983L,52984L,52985L,52986L,52987L,
89206 52988L,52989L,52990L,52991L,52992L,52993L,52994L,52995L,52996L,52997L,
89207 52998L,52999L,53000L,53001L,53002L,53003L,53004L,53005L,53006L,53007L,
89208 53008L,53009L,53010L,53011L,53012L,53013L,53014L,53015L,53016L,53017L,
89209 53018L,53019L,53020L,53021L,53022L,53023L,53024L,53025L,53026L,53027L,
89210 53028L,53029L,53030L,53031L,53032L,53033L,53034L,53035L,53036L,53037L,
89211 53038L,53039L,53040L,53041L,53042L,53043L,53044L,53045L,53046L,53047L,
89212 53048L,53049L,53050L,53051L,53052L,53053L,53054L,53055L,53056L,53057L,
89213 53058L,53059L,53060L,53061L,53062L,53063L,53064L,53065L,53066L,53067L,
89214 53068L,53069L,53070L,53071L,53072L,53073L,53074L,53075L,53076L,53077L,
89215 53078L,53079L,53080L,53081L,53082L,53083L,53084L,53085L,53086L,53087L,
89216 53088L,53089L,53090L,53091L,53092L,53093L,53094L,53095L,53096L,53097L,
89217 53098L,53099L,53100L,53101L,53102L,53103L,53104L,53105L,53106L,53107L,
89218 53108L,53109L,53110L,53111L,53112L,53113L,53114L,53115L,53116L,53117L,
89219 53118L,53119L,53120L,53121L,53122L,53123L,53124L,53125L,53126L,53127L,
89220 53128L,53129L,53130L,53131L,53132L,53133L,53134L,53135L,53136L,53137L,
89221 53138L,53139L,53140L,53141L,53142L,53143L,53144L,53145L,53146L,53147L,
89222 53148L,53149L,53150L,53151L,53152L,53153L,53154L,53155L,53156L,53157L,
89223 53158L,53159L,53160L,53161L,53162L,53163L,53164L,53165L,53166L,53167L,
89224 53168L,53169L,53170L,53171L,53172L,53173L,53174L,53175L,53176L,53177L,
89225 53178L,53179L,53180L,53181L,53182L,53183L,53184L,53185L,53186L,53187L,
89226 53188L,53189L,53190L,53191L,53192L,53193L,53194L,53195L,53196L,53197L,
89227 53198L,53199L,53200L,53201L,53202L,53203L,53204L,53205L,53206L,53207L,
89228 53208L,53209L,53210L,53211L,53212L,53213L,53214L,53215L,53216L,53217L,
89229 53218L,53219L,53220L,53221L,53222L,53223L,53224L,53225L,53226L,53227L,
89230 53228L,53229L,53230L,53231L,53232L,53233L,53234L,53235L,53236L,53237L,
89231 53238L,53239L,53240L,53241L,53242L,53243L,53244L,53245L,53246L,53247L,
89232 53248L,53249L,53250L,53251L,53252L,53253L,53254L,53255L,53256L,53257L,
89233 53258L,53259L,53260L,53261L,53262L,53263L,53264L,53265L,53266L,53267L,
89234 53268L,53269L,53270L,53271L,53272L,53273L,53274L,53275L,53276L,53277L,
89235 53278L,53279L,53280L,53281L,53282L,53283L,53284L,53285L,53286L,53287L,
89236 53288L,53289L,53290L,53291L,53292L,53293L,53294L,53295L,53296L,53297L,
89237 53298L,53299L,53300L,53301L,53302L,53303L,53304L,53305L,53306L,53307L,
89238 53308L,53309L,53310L,53311L,53312L,53313L,53314L,53315L,53316L,53317L,
89239 53318L,53319L,53320L,53321L,53322L,53323L,53324L,53325L,53326L,53327L,
89240 53328L,53329L,53330L,53331L,53332L,53333L,53334L,53335L,53336L,53337L,
89241 53338L,53339L,53340L,53341L,53342L,53343L,53344L,53345L,53346L,53347L,
89242 53348L,53349L,53350L,53351L,53352L,53353L,53354L,53355L,53356L,53357L,
89243 53358L,53359L,53360L,53361L,53362L,53363L,53364L,53365L,53366L,53367L,
89244 53368L,53369L,53370L,53371L,53372L,53373L,53374L,53375L,53376L,53377L,
89245 53378L,53379L,53380L,53381L,53382L,53383L,53384L,53385L,53386L,53387L,
89246 53388L,53389L,53390L,53391L,53392L,53393L,53394L,53395L,53396L,53397L,
89247 53398L,53399L,53400L,53401L,53402L,53403L,53404L,53405L,53406L,53407L,
89248 53408L,53409L,53410L,53411L,53412L,53413L,53414L,53415L,53416L,53417L,
89249 53418L,53419L,53420L,53421L,53422L,53423L,53424L,53425L,53426L,53427L,
89250 53428L,53429L,53430L,53431L,53432L,53433L,53434L,53435L,53436L,53437L,
89251 53438L,53439L,53440L,53441L,53442L,53443L,53444L,53445L,53446L,53447L,
89252 53448L,53449L,53450L,53451L,53452L,53453L,53454L,53455L,53456L,53457L,
89253 53458L,53459L,53460L,53461L,53462L,53463L,53464L,53465L,53466L,53467L,
89254 53468L,53469L,53470L,53471L,53472L,53473L,53474L,53475L,53476L,53477L,
89255 53478L,53479L,53480L,53481L,53482L,53483L,53484L,53485L,53486L,53487L,
89256 53488L,53489L,53490L,53491L,53492L,53493L,53494L,53495L,53496L,53497L,
89257 53498L,53499L,53500L,53501L,53502L,53503L,53504L,53505L,53506L,53507L,
89258 53508L,53509L,53510L,53511L,53512L,53513L,53514L,53515L,53516L,53517L,
89259 53518L,53519L,53520L,53521L,53522L,53523L,53524L,53525L,53526L,53527L,
89260 53528L,53529L,53530L,53531L,53532L,53533L,53534L,53535L,53536L,53537L,
89261 53538L,53539L,53540L,53541L,53542L,53543L,53544L,53545L,53546L,53547L,
89262 53548L,53549L,53550L,53551L,53552L,53553L,53554L,53555L,53556L,53557L,
89263 53558L,53559L,53560L,53561L,53562L,53563L,53564L,53565L,53566L,53567L,
89264 53568L,53569L,53570L,53571L,53572L,53573L,53574L,53575L,53576L,53577L,
89265 53578L,53579L,53580L,53581L,53582L,53583L,53584L,53585L,53586L,53587L,
89266 53588L,53589L,53590L,53591L,53592L,53593L,53594L,53595L,53596L,53597L,
89267 53598L,53599L,53600L,53601L,53602L,53603L,53604L,53605L,53606L,53607L,
89268 53608L,53609L,53610L,53611L,53612L,53613L,53614L,53615L,53616L,53617L,
89269 53618L,53619L,53620L,53621L,53622L,53623L,53624L,53625L,53626L,53627L,
89270 53628L,53629L,53630L,53631L,53632L,53633L,53634L,53635L,53636L,53637L,
89271 53638L,53639L,53640L,53641L,53642L,53643L,53644L,53645L,53646L,53647L,
89272 53648L,53649L,53650L,53651L,53652L,53653L,53654L,53655L,53656L,53657L,
89273 53658L,53659L,53660L,53661L,53662L,53663L,53664L,53665L,53666L,53667L,
89274 53668L,53669L,53670L,53671L,53672L,53673L,53674L,53675L,53676L,53677L,
89275 53678L,53679L,53680L,53681L,53682L,53683L,53684L,53685L,53686L,53687L,
89276 53688L,53689L,53690L,53691L,53692L,53693L,53694L,53695L,53696L,53697L,
89277 53698L,53699L,53700L,53701L,53702L,53703L,53704L,53705L,53706L,53707L,
89278 53708L,53709L,53710L,53711L,53712L,53713L,53714L,53715L,53716L,53717L,
89279 53718L,53719L,53720L,53721L,53722L,53723L,53724L,53725L,53726L,53727L,
89280 53728L,53729L,53730L,53731L,53732L,53733L,53734L,53735L,53736L,53737L,
89281 53738L,53739L,53740L,53741L,53742L,53743L,53744L,53745L,53746L,53747L,
89282 53748L,53749L,53750L,53751L,53752L,53753L,53754L,53755L,53756L,53757L,
89283 53758L,53759L,53760L,53761L,53762L,53763L,53764L,53765L,53766L,53767L,
89284 53768L,53769L,53770L,53771L,53772L,53773L,53774L,53775L,53776L,53777L,
89285 53778L,53779L,53780L,53781L,53782L,53783L,53784L,53785L,53786L,53787L,
89286 53788L,53789L,53790L,53791L,53792L,53793L,53794L,53795L,53796L,53797L,
89287 53798L,53799L,53800L,53801L,53802L,53803L,53804L,53805L,53806L,53807L,
89288 53808L,53809L,53810L,53811L,53812L,53813L,53814L,53815L,53816L,53817L,
89289 53818L,53819L,53820L,53821L,53822L,53823L,53824L,53825L,53826L,53827L,
89290 53828L,53829L,53830L,53831L,53832L,53833L,53834L,53835L,53836L,53837L,
89291 53838L,53839L,53840L,53841L,53842L,53843L,53844L,53845L,53846L,53847L,
89292 53848L,53849L,53850L,53851L,53852L,53853L,53854L,53855L,53856L,53857L,
89293 53858L,53859L,53860L,53861L,53862L,53863L,53864L,53865L,53866L,53867L,
89294 53868L,53869L,53870L,53871L,53872L,53873L,53874L,53875L,53876L,53877L,
89295 53878L,53879L,53880L,53881L,53882L,53883L,53884L,53885L,53886L,53887L,
89296 53888L,53889L,53890L,53891L,53892L,53893L,53894L,53895L,53896L,53897L,
89297 53898L,53899L,53900L,53901L,53902L,53903L,53904L,53905L,53906L,53907L,
89298 53908L,53909L,53910L,53911L,53912L,53913L,53914L,53915L,53916L,53917L,
89299 53918L,53919L,53920L,53921L,53922L,53923L,53924L,53925L,53926L,53927L,
89300 53928L,53929L,53930L,53931L,53932L,53933L,53934L,53935L,53936L,53937L,
89301 53938L,53939L,53940L,53941L,53942L,53943L,53944L,53945L,53946L,53947L,
89302 53948L,53949L,53950L,53951L,53952L,53953L,53954L,53955L,53956L,53957L,
89303 53958L,53959L,53960L,53961L,53962L,53963L,53964L,53965L,53966L,53967L,
89304 53968L,53969L,53970L,53971L,53972L,53973L,53974L,53975L,53976L,53977L,
89305 53978L,53979L,53980L,53981L,53982L,53983L,53984L,53985L,53986L,53987L,
89306 53988L,53989L,53990L,53991L,53992L,53993L,53994L,53995L,53996L,53997L,
89307 53998L,53999L,54000L,54001L,54002L,54003L,54004L,54005L,54006L,54007L,
89308 54008L,54009L,54010L,54011L,54012L,54013L,54014L,54015L,54016L,54017L,
89309 54018L,54019L,54020L,54021L,54022L,54023L,54024L,54025L,54026L,54027L,
89310 54028L,54029L,54030L,54031L,54032L,54033L,54034L,54035L,54036L,54037L,
89311 54038L,54039L,54040L,54041L,54042L,54043L,54044L,54045L,54046L,54047L,
89312 54048L,54049L,54050L,54051L,54052L,54053L,54054L,54055L,54056L,54057L,
89313 54058L,54059L,54060L,54061L,54062L,54063L,54064L,54065L,54066L,54067L,
89314 54068L,54069L,54070L,54071L,54072L,54073L,54074L,54075L,54076L,54077L,
89315 54078L,54079L,54080L,54081L,54082L,54083L,54084L,54085L,54086L,54087L,
89316 54088L,54089L,54090L,54091L,54092L,54093L,54094L,54095L,54096L,54097L,
89317 54098L,54099L,54100L,54101L,54102L,54103L,54104L,54105L,54106L,54107L,
89318 54108L,54109L,54110L,54111L,54112L,54113L,54114L,54115L,54116L,54117L,
89319 54118L,54119L,54120L,54121L,54122L,54123L,54124L,54125L,54126L,54127L,
89320 54128L,54129L,54130L,54131L,54132L,54133L,54134L,54135L,54136L,54137L,
89321 54138L,54139L,54140L,54141L,54142L,54143L,54144L,54145L,54146L,54147L,
89322 54148L,54149L,54150L,54151L,54152L,54153L,54154L,54155L,54156L,54157L,
89323 54158L,54159L,54160L,54161L,54162L,54163L,54164L,54165L,54166L,54167L,
89324 54168L,54169L,54170L,54171L,54172L,54173L,54174L,54175L,54176L,54177L,
89325 54178L,54179L,54180L,54181L,54182L,54183L,54184L,54185L,54186L,54187L,
89326 54188L,54189L,54190L,54191L,54192L,54193L,54194L,54195L,54196L,54197L,
89327 54198L,54199L,54200L,54201L,54202L,54203L,54204L,54205L,54206L,54207L,
89328 54208L,54209L,54210L,54211L,54212L,54213L,54214L,54215L,54216L,54217L,
89329 54218L,54219L,54220L,54221L,54222L,54223L,54224L,54225L,54226L,54227L,
89330 54228L,54229L,54230L,54231L,54232L,54233L,54234L,54235L,54236L,54237L,
89331 54238L,54239L,54240L,54241L,54242L,54243L,54244L,54245L,54246L,54247L,
89332 54248L,54249L,54250L,54251L,54252L,54253L,54254L,54255L,54256L,54257L,
89333 54258L,54259L,54260L,54261L,54262L,54263L,54264L,54265L,54266L,54267L,
89334 54268L,54269L,54270L,54271L,54272L,54273L,54274L,54275L,54276L,54277L,
89335 54278L,54279L,54280L,54281L,54282L,54283L,54284L,54285L,54286L,54287L,
89336 54288L,54289L,54290L,54291L,54292L,54293L,54294L,54295L,54296L,54297L,
89337 54298L,54299L,54300L,54301L,54302L,54303L,54304L,54305L,54306L,54307L,
89338 54308L,54309L,54310L,54311L,54312L,54313L,54314L,54315L,54316L,54317L,
89339 54318L,54319L,54320L,54321L,54322L,54323L,54324L,54325L,54326L,54327L,
89340 54328L,54329L,54330L,54331L,54332L,54333L,54334L,54335L,54336L,54337L,
89341 54338L,54339L,54340L,54341L,54342L,54343L,54344L,54345L,54346L,54347L,
89342 54348L,54349L,54350L,54351L,54352L,54353L,54354L,54355L,54356L,54357L,
89343 54358L,54359L,54360L,54361L,54362L,54363L,54364L,54365L,54366L,54367L,
89344 54368L,54369L,54370L,54371L,54372L,54373L,54374L,54375L,54376L,54377L,
89345 54378L,54379L,54380L,54381L,54382L,54383L,54384L,54385L,54386L,54387L,
89346 54388L,54389L,54390L,54391L,54392L,54393L,54394L,54395L,54396L,54397L,
89347 54398L,54399L,54400L,54401L,54402L,54403L,54404L,54405L,54406L,54407L,
89348 54408L,54409L,54410L,54411L,54412L,54413L,54414L,54415L,54416L,54417L,
89349 54418L,54419L,54420L,54421L,54422L,54423L,54424L,54425L,54426L,54427L,
89350 54428L,54429L,54430L,54431L,54432L,54433L,54434L,54435L,54436L,54437L,
89351 54438L,54439L,54440L,54441L,54442L,54443L,54444L,54445L,54446L,54447L,
89352 54448L,54449L,54450L,54451L,54452L,54453L,54454L,54455L,54456L,54457L,
89353 54458L,54459L,54460L,54461L,54462L,54463L,54464L,54465L,54466L,54467L,
89354 54468L,54469L,54470L,54471L,54472L,54473L,54474L,54475L,54476L,54477L,
89355 54478L,54479L,54480L,54481L,54482L,54483L,54484L,54485L,54486L,54487L,
89356 54488L,54489L,54490L,54491L,54492L,54493L,54494L,54495L,54496L,54497L,
89357 54498L,54499L,54500L,54501L,54502L,54503L,54504L,54505L,54506L,54507L,
89358 54508L,54509L,54510L,54511L,54512L,54513L,54514L,54515L,54516L,54517L,
89359 54518L,54519L,54520L,54521L,54522L,54523L,54524L,54525L,54526L,54527L,
89360 54528L,54529L,54530L,54531L,54532L,54533L,54534L,54535L,54536L,54537L,
89361 54538L,54539L,54540L,54541L,54542L,54543L,54544L,54545L,54546L,54547L,
89362 54548L,54549L,54550L,54551L,54552L,54553L,54554L,54555L,54556L,54557L,
89363 54558L,54559L,54560L,54561L,54562L,54563L,54564L,54565L,54566L,54567L,
89364 54568L,54569L,54570L,54571L,54572L,54573L,54574L,54575L,54576L,54577L,
89365 54578L,54579L,54580L,54581L,54582L,54583L,54584L,54585L,54586L,54587L,
89366 54588L,54589L,54590L,54591L,54592L,54593L,54594L,54595L,54596L,54597L,
89367 54598L,54599L,54600L,54601L,54602L,54603L,54604L,54605L,54606L,54607L,
89368 54608L,54609L,54610L,54611L,54612L,54613L,54614L,54615L,54616L,54617L,
89369 54618L,54619L,54620L,54621L,54622L,54623L,54624L,54625L,54626L,54627L,
89370 54628L,54629L,54630L,54631L,54632L,54633L,54634L,54635L,54636L,54637L,
89371 54638L,54639L,54640L,54641L,54642L,54643L,54644L,54645L,54646L,54647L,
89372 54648L,54649L,54650L,54651L,54652L,54653L,54654L,54655L,54656L,54657L,
89373 54658L,54659L,54660L,54661L,54662L,54663L,54664L,54665L,54666L,54667L,
89374 54668L,54669L,54670L,54671L,54672L,54673L,54674L,54675L,54676L,54677L,
89375 54678L,54679L,54680L,54681L,54682L,54683L,54684L,54685L,54686L,54687L,
89376 54688L,54689L,54690L,54691L,54692L,54693L,54694L,54695L,54696L,54697L,
89377 54698L,54699L,54700L,54701L,54702L,54703L,54704L,54705L,54706L,54707L,
89378 54708L,54709L,54710L,54711L,54712L,54713L,54714L,54715L,54716L,54717L,
89379 54718L,54719L,54720L,54721L,54722L,54723L,54724L,54725L,54726L,54727L,
89380 54728L,54729L,54730L,54731L,54732L,54733L,54734L,54735L,54736L,54737L,
89381 54738L,54739L,54740L,54741L,54742L,54743L,54744L,54745L,54746L,54747L,
89382 54748L,54749L,54750L,54751L,54752L,54753L,54754L,54755L,54756L,54757L,
89383 54758L,54759L,54760L,54761L,54762L,54763L,54764L,54765L,54766L,54767L,
89384 54768L,54769L,54770L,54771L,54772L,54773L,54774L,54775L,54776L,54777L,
89385 54778L,54779L,54780L,54781L,54782L,54783L,54784L,54785L,54786L,54787L,
89386 54788L,54789L,54790L,54791L,54792L,54793L,54794L,54795L,54796L,54797L,
89387 54798L,54799L,54800L,54801L,54802L,54803L,54804L,54805L,54806L,54807L,
89388 54808L,54809L,54810L,54811L,54812L,54813L,54814L,54815L,54816L,54817L,
89389 54818L,54819L,54820L,54821L,54822L,54823L,54824L,54825L,54826L,54827L,
89390 54828L,54829L,54830L,54831L,54832L,54833L,54834L,54835L,54836L,54837L,
89391 54838L,54839L,54840L,54841L,54842L,54843L,54844L,54845L,54846L,54847L,
89392 54848L,54849L,54850L,54851L,54852L,54853L,54854L,54855L,54856L,54857L,
89393 54858L,54859L,54860L,54861L,54862L,54863L,54864L,54865L,54866L,54867L,
89394 54868L,54869L,54870L,54871L,54872L,54873L,54874L,54875L,54876L,54877L,
89395 54878L,54879L,54880L,54881L,54882L,54883L,54884L,54885L,54886L,54887L,
89396 54888L,54889L,54890L,54891L,54892L,54893L,54894L,54895L,54896L,54897L,
89397 54898L,54899L,54900L,54901L,54902L,54903L,54904L,54905L,54906L,54907L,
89398 54908L,54909L,54910L,54911L,54912L,54913L,54914L,54915L,54916L,54917L,
89399 54918L,54919L,54920L,54921L,54922L,54923L,54924L,54925L,54926L,54927L,
89400 54928L,54929L,54930L,54931L,54932L,54933L,54934L,54935L,54936L,54937L,
89401 54938L,54939L,54940L,54941L,54942L,54943L,54944L,54945L,54946L,54947L,
89402 54948L,54949L,54950L,54951L,54952L,54953L,54954L,54955L,54956L,54957L,
89403 54958L,54959L,54960L,54961L,54962L,54963L,54964L,54965L,54966L,54967L,
89404 54968L,54969L,54970L,54971L,54972L,54973L,54974L,54975L,54976L,54977L,
89405 54978L,54979L,54980L,54981L,54982L,54983L,54984L,54985L,54986L,54987L,
89406 54988L,54989L,54990L,54991L,54992L,54993L,54994L,54995L,54996L,54997L,
89407 54998L,54999L,55000L,55001L,55002L,55003L,55004L,55005L,55006L,55007L,
89408 55008L,55009L,55010L,55011L,55012L,55013L,55014L,55015L,55016L,55017L,
89409 55018L,55019L,55020L,55021L,55022L,55023L,55024L,55025L,55026L,55027L,
89410 55028L,55029L,55030L,55031L,55032L,55033L,55034L,55035L,55036L,55037L,
89411 55038L,55039L,55040L,55041L,55042L,55043L,55044L,55045L,55046L,55047L,
89412 55048L,55049L,55050L,55051L,55052L,55053L,55054L,55055L,55056L,55057L,
89413 55058L,55059L,55060L,55061L,55062L,55063L,55064L,55065L,55066L,55067L,
89414 55068L,55069L,55070L,55071L,55072L,55073L,55074L,55075L,55076L,55077L,
89415 55078L,55079L,55080L,55081L,55082L,55083L,55084L,55085L,55086L,55087L,
89416 55088L,55089L,55090L,55091L,55092L,55093L,55094L,55095L,55096L,55097L,
89417 55098L,55099L,55100L,55101L,55102L,55103L,55104L,55105L,55106L,55107L,
89418 55108L,55109L,55110L,55111L,55112L,55113L,55114L,55115L,55116L,55117L,
89419 55118L,55119L,55120L,55121L,55122L,55123L,55124L,55125L,55126L,55127L,
89420 55128L,55129L,55130L,55131L,55132L,55133L,55134L,55135L,55136L,55137L,
89421 55138L,55139L,55140L,55141L,55142L,55143L,55144L,55145L,55146L,55147L,
89422 55148L,55149L,55150L,55151L,55152L,55153L,55154L,55155L,55156L,55157L,
89423 55158L,55159L,55160L,55161L,55162L,55163L,55164L,55165L,55166L,55167L,
89424 55168L,55169L,55170L,55171L,55172L,55173L,55174L,55175L,55176L,55177L,
89425 55178L,55179L,55180L,55181L,55182L,55183L,55184L,55185L,55186L,55187L,
89426 55188L,55189L,55190L,55191L,55192L,55193L,55194L,55195L,55196L,55197L,
89427 55198L,55199L,55200L,55201L,55202L,55203L,55204L,55205L,55206L,55207L,
89428 55208L,55209L,55210L,55211L,55212L,55213L,55214L,55215L,55216L,55217L,
89429 55218L,55219L,55220L,55221L,55222L,55223L,55224L,55225L,55226L,55227L,
89430 55228L,55229L,55230L,55231L,55232L,55233L,55234L,55235L,55236L,55237L,
89431 55238L,55239L,55240L,55241L,55242L,55243L,55244L,55245L,55246L,55247L,
89432 55248L,55249L,55250L,55251L,55252L,55253L,55254L,55255L,55256L,55257L,
89433 55258L,55259L,55260L,55261L,55262L,55263L,55264L,55265L,55266L,55267L,
89434 55268L,55269L,55270L,55271L,55272L,55273L,55274L,55275L,55276L,55277L,
89435 55278L,55279L,55280L,55281L,55282L,55283L,55284L,55285L,55286L,55287L,
89436 55288L,55289L,55290L,55291L,55292L,55293L,55294L,55295L,55296L,55297L,
89437 55298L,55299L,55300L,55301L,55302L,55303L,55304L,55305L,55306L,55307L,
89438 55308L,55309L,55310L,55311L,55312L,55313L,55314L,55315L,55316L,55317L,
89439 55318L,55319L,55320L,55321L,55322L,55323L,55324L,55325L,55326L,55327L,
89440 55328L,55329L,55330L,55331L,55332L,55333L,55334L,55335L,55336L,55337L,
89441 55338L,55339L,55340L,55341L,55342L,55343L,55344L,55345L,55346L,55347L,
89442 55348L,55349L,55350L,55351L,55352L,55353L,55354L,55355L,55356L,55357L,
89443 55358L,55359L,55360L,55361L,55362L,55363L,55364L,55365L,55366L,55367L,
89444 55368L,55369L,55370L,55371L,55372L,55373L,55374L,55375L,55376L,55377L,
89445 55378L,55379L,55380L,55381L,55382L,55383L,55384L,55385L,55386L,55387L,
89446 55388L,55389L,55390L,55391L,55392L,55393L,55394L,55395L,55396L,55397L,
89447 55398L,55399L,55400L,55401L,55402L,55403L,55404L,55405L,55406L,55407L,
89448 55408L,55409L,55410L,55411L,55412L,55413L,55414L,55415L,55416L,55417L,
89449 55418L,55419L,55420L,55421L,55422L,55423L,55424L,55425L,55426L,55427L,
89450 55428L,55429L,55430L,55431L,55432L,55433L,55434L,55435L,55436L,55437L,
89451 55438L,55439L,55440L,55441L,55442L,55443L,55444L,55445L,55446L,55447L,
89452 55448L,55449L,55450L,55451L,55452L,55453L,55454L,55455L,55456L,55457L,
89453 55458L,55459L,55460L,55461L,55462L,55463L,55464L,55465L,55466L,55467L,
89454 55468L,55469L,55470L,55471L,55472L,55473L,55474L,55475L,55476L,55477L,
89455 55478L,55479L,55480L,55481L,55482L,55483L,55484L,55485L,55486L,55487L,
89456 55488L,55489L,55490L,55491L,55492L,55493L,55494L,55495L,55496L,55497L,
89457 55498L,55499L,55500L,55501L,55502L,55503L,55504L,55505L,55506L,55507L,
89458 55508L,55509L,55510L,55511L,55512L,55513L,55514L,55515L,55516L,55517L,
89459 55518L,55519L,55520L,55521L,55522L,55523L,55524L,55525L,55526L,55527L,
89460 55528L,55529L,55530L,55531L,55532L,55533L,55534L,55535L,55536L,55537L,
89461 55538L,55539L,55540L,55541L,55542L,55543L,55544L,55545L,55546L,55547L,
89462 55548L,55549L,55550L,55551L,55552L,55553L,55554L,55555L,55556L,55557L,
89463 55558L,55559L,55560L,55561L,55562L,55563L,55564L,55565L,55566L,55567L,
89464 55568L,55569L,55570L,55571L,55572L,55573L,55574L,55575L,55576L,55577L,
89465 55578L,55579L,55580L,55581L,55582L,55583L,55584L,55585L,55586L,55587L,
89466 55588L,55589L,55590L,55591L,55592L,55593L,55594L,55595L,55596L,55597L,
89467 55598L,55599L,55600L,55601L,55602L,55603L,55604L,55605L,55606L,55607L,
89468 55608L,55609L,55610L,55611L,55612L,55613L,55614L,55615L,55616L,55617L,
89469 55618L,55619L,55620L,55621L,55622L,55623L,55624L,55625L,55626L,55627L,
89470 55628L,55629L,55630L,55631L,55632L,55633L,55634L,55635L,55636L,55637L,
89471 55638L,55639L,55640L,55641L,55642L,55643L,55644L,55645L,55646L,55647L,
89472 55648L,55649L,55650L,55651L,55652L,55653L,55654L,55655L,55656L,55657L,
89473 55658L,55659L,55660L,55661L,55662L,55663L,55664L,55665L,55666L,55667L,
89474 55668L,55669L,55670L,55671L,55672L,55673L,55674L,55675L,55676L,55677L,
89475 55678L,55679L,55680L,55681L,55682L,55683L,55684L,55685L,55686L,55687L,
89476 55688L,55689L,55690L,55691L,55692L,55693L,55694L,55695L,55696L,55697L,
89477 55698L,55699L,55700L,55701L,55702L,55703L,55704L,55705L,55706L,55707L,
89478 55708L,55709L,55710L,55711L,55712L,55713L,55714L,55715L,55716L,55717L,
89479 55718L,55719L,55720L,55721L,55722L,55723L,55724L,55725L,55726L,55727L,
89480 55728L,55729L,55730L,55731L,55732L,55733L,55734L,55735L,55736L,55737L,
89481 55738L,55739L,55740L,55741L,55742L,55743L,55744L,55745L,55746L,55747L,
89482 55748L,55749L,55750L,55751L,55752L,55753L,55754L,55755L,55756L,55757L,
89483 55758L,55759L,55760L,55761L,55762L,55763L,55764L,55765L,55766L,55767L,
89484 55768L,55769L,55770L,55771L,55772L,55773L,55774L,55775L,55776L,55777L,
89485 55778L,55779L,55780L,55781L,55782L,55783L,55784L,55785L,55786L,55787L,
89486 55788L,55789L,55790L,55791L,55792L,55793L,55794L,55795L,55796L,55797L,
89487 55798L,55799L,55800L,55801L,55802L,55803L,55804L,55805L,55806L,55807L,
89488 55808L,55809L,55810L,55811L,55812L,55813L,55814L,55815L,55816L,55817L,
89489 55818L,55819L,55820L,55821L,55822L,55823L,55824L,55825L,55826L,55827L,
89490 55828L,55829L,55830L,55831L,55832L,55833L,55834L,55835L,55836L,55837L,
89491 55838L,55839L,55840L,55841L,55842L,55843L,55844L,55845L,55846L,55847L,
89492 55848L,55849L,55850L,55851L,55852L,55853L,55854L,55855L,55856L,55857L,
89493 55858L,55859L,55860L,55861L,55862L,55863L,55864L,55865L,55866L,55867L,
89494 55868L,55869L,55870L,55871L,55872L,55873L,55874L,55875L,55876L,55877L,
89495 55878L,55879L,55880L,55881L,55882L,55883L,55884L,55885L,55886L,55887L,
89496 55888L,55889L,55890L,55891L,55892L,55893L,55894L,55895L,55896L,55897L,
89497 55898L,55899L,55900L,55901L,55902L,55903L,55904L,55905L,55906L,55907L,
89498 55908L,55909L,55910L,55911L,55912L,55913L,55914L,55915L,55916L,55917L,
89499 55918L,55919L,55920L,55921L,55922L,55923L,55924L,55925L,55926L,55927L,
89500 55928L,55929L,55930L,55931L,55932L,55933L,55934L,55935L,55936L,55937L,
89501 55938L,55939L,55940L,55941L,55942L,55943L,55944L,55945L,55946L,55947L,
89502 55948L,55949L,55950L,55951L,55952L,55953L,55954L,55955L,55956L,55957L,
89503 55958L,55959L,55960L,55961L,55962L,55963L,55964L,55965L,55966L,55967L,
89504 55968L,55969L,55970L,55971L,55972L,55973L,55974L,55975L,55976L,55977L,
89505 55978L,55979L,55980L,55981L,55982L,55983L,55984L,55985L,55986L,55987L,
89506 55988L,55989L,55990L,55991L,55992L,55993L,55994L,55995L,55996L,55997L,
89507 55998L,55999L,56000L,56001L,56002L,56003L,56004L,56005L,56006L,56007L,
89508 56008L,56009L,56010L,56011L,56012L,56013L,56014L,56015L,56016L,56017L,
89509 56018L,56019L,56020L,56021L,56022L,56023L,56024L,56025L,56026L,56027L,
89510 56028L,56029L,56030L,56031L,56032L,56033L,56034L,56035L,56036L,56037L,
89511 56038L,56039L,56040L,56041L,56042L,56043L,56044L,56045L,56046L,56047L,
89512 56048L,56049L,56050L,56051L,56052L,56053L,56054L,56055L,56056L,56057L,
89513 56058L,56059L,56060L,56061L,56062L,56063L,56064L,56065L,56066L,56067L,
89514 56068L,56069L,56070L,56071L,56072L,56073L,56074L,56075L,56076L,56077L,
89515 56078L,56079L,56080L,56081L,56082L,56083L,56084L,56085L,56086L,56087L,
89516 56088L,56089L,56090L,56091L,56092L,56093L,56094L,56095L,56096L,56097L,
89517 56098L,56099L,56100L,56101L,56102L,56103L,56104L,56105L,56106L,56107L,
89518 56108L,56109L,56110L,56111L,56112L,56113L,56114L,56115L,56116L,56117L,
89519 56118L,56119L,56120L,56121L,56122L,56123L,56124L,56125L,56126L,56127L,
89520 56128L,56129L,56130L,56131L,56132L,56133L,56134L,56135L,56136L,56137L,
89521 56138L,56139L,56140L,56141L,56142L,56143L,56144L,56145L,56146L,56147L,
89522 56148L,56149L,56150L,56151L,56152L,56153L,56154L,56155L,56156L,56157L,
89523 56158L,56159L,56160L,56161L,56162L,56163L,56164L,56165L,56166L,56167L,
89524 56168L,56169L,56170L,56171L,56172L,56173L,56174L,56175L,56176L,56177L,
89525 56178L,56179L,56180L,56181L,56182L,56183L,56184L,56185L,56186L,56187L,
89526 56188L,56189L,56190L,56191L,56192L,56193L,56194L,56195L,56196L,56197L,
89527 56198L,56199L,56200L,56201L,56202L,56203L,56204L,56205L,56206L,56207L,
89528 56208L,56209L,56210L,56211L,56212L,56213L,56214L,56215L,56216L,56217L,
89529 56218L,56219L,56220L,56221L,56222L,56223L,56224L,56225L,56226L,56227L,
89530 56228L,56229L,56230L,56231L,56232L,56233L,56234L,56235L,56236L,56237L,
89531 56238L,56239L,56240L,56241L,56242L,56243L,56244L,56245L,56246L,56247L,
89532 56248L,56249L,56250L,56251L,56252L,56253L,56254L,56255L,56256L,56257L,
89533 56258L,56259L,56260L,56261L,56262L,56263L,56264L,56265L,56266L,56267L,
89534 56268L,56269L,56270L,56271L,56272L,56273L,56274L,56275L,56276L,56277L,
89535 56278L,56279L,56280L,56281L,56282L,56283L,56284L,56285L,56286L,56287L,
89536 56288L,56289L,56290L,56291L,56292L,56293L,56294L,56295L,56296L,56297L,
89537 56298L,56299L,56300L,56301L,56302L,56303L,56304L,56305L,56306L,56307L,
89538 56308L,56309L,56310L,56311L,56312L,56313L,56314L,56315L,56316L,56317L,
89539 56318L,56319L,56320L,56321L,56322L,56323L,56324L,56325L,56326L,56327L,
89540 56328L,56329L,56330L,56331L,56332L,56333L,56334L,56335L,56336L,56337L,
89541 56338L,56339L,56340L,56341L,56342L,56343L,56344L,56345L,56346L,56347L,
89542 56348L,56349L,56350L,56351L,56352L,56353L,56354L,56355L,56356L,56357L,
89543 56358L,56359L,56360L,56361L,56362L,56363L,56364L,56365L,56366L,56367L,
89544 56368L,56369L,56370L,56371L,56372L,56373L,56374L,56375L,56376L,56377L,
89545 56378L,56379L,56380L,56381L,56382L,56383L,56384L,56385L,56386L,56387L,
89546 56388L,56389L,56390L,56391L,56392L,56393L,56394L,56395L,56396L,56397L,
89547 56398L,56399L,56400L,56401L,56402L,56403L,56404L,56405L,56406L,56407L,
89548 56408L,56409L,56410L,56411L,56412L,56413L,56414L,56415L,56416L,56417L,
89549 56418L,56419L,56420L,56421L,56422L,56423L,56424L,56425L,56426L,56427L,
89550 56428L,56429L,56430L,56431L,56432L,56433L,56434L,56435L,56436L,56437L,
89551 56438L,56439L,56440L,56441L,56442L,56443L,56444L,56445L,56446L,56447L,
89552 56448L,56449L,56450L,56451L,56452L,56453L,56454L,56455L,56456L,56457L,
89553 56458L,56459L,56460L,56461L,56462L,56463L,56464L,56465L,56466L,56467L,
89554 56468L,56469L,56470L,56471L,56472L,56473L,56474L,56475L,56476L,56477L,
89555 56478L,56479L,56480L,56481L,56482L,56483L,56484L,56485L,56486L,56487L,
89556 56488L,56489L,56490L,56491L,56492L,56493L,56494L,56495L,56496L,56497L,
89557 56498L,56499L,56500L,56501L,56502L,56503L,56504L,56505L,56506L,56507L,
89558 56508L,56509L,56510L,56511L,56512L,56513L,56514L,56515L,56516L,56517L,
89559 56518L,56519L,56520L,56521L,56522L,56523L,56524L,56525L,56526L,56527L,
89560 56528L,56529L,56530L,56531L,56532L,56533L,56534L,56535L,56536L,56537L,
89561 56538L,56539L,56540L,56541L,56542L,56543L,56544L,56545L,56546L,56547L,
89562 56548L,56549L,56550L,56551L,56552L,56553L,56554L,56555L,56556L,56557L,
89563 56558L,56559L,56560L,56561L,56562L,56563L,56564L,56565L,56566L,56567L,
89564 56568L,56569L,56570L,56571L,56572L,56573L,56574L,56575L,56576L,56577L,
89565 56578L,56579L,56580L,56581L,56582L,56583L,56584L,56585L,56586L,56587L,
89566 56588L,56589L,56590L,56591L,56592L,56593L,56594L,56595L,56596L,56597L,
89567 56598L,56599L,56600L,56601L,56602L,56603L,56604L,56605L,56606L,56607L,
89568 56608L,56609L,56610L,56611L,56612L,56613L,56614L,56615L,56616L,56617L,
89569 56618L,56619L,56620L,56621L,56622L,56623L,56624L,56625L,56626L,56627L,
89570 56628L,56629L,56630L,56631L,56632L,56633L,56634L,56635L,56636L,56637L,
89571 56638L,56639L,56640L,56641L,56642L,56643L,56644L,56645L,56646L,56647L,
89572 56648L,56649L,56650L,56651L,56652L,56653L,56654L,56655L,56656L,56657L,
89573 56658L,56659L,56660L,56661L,56662L,56663L,56664L,56665L,56666L,56667L,
89574 56668L,56669L,56670L,56671L,56672L,56673L,56674L,56675L,56676L,56677L,
89575 56678L,56679L,56680L,56681L,56682L,56683L,56684L,56685L,56686L,56687L,
89576 56688L,56689L,56690L,56691L,56692L,56693L,56694L,56695L,56696L,56697L,
89577 56698L,56699L,56700L,56701L,56702L,56703L,56704L,56705L,56706L,56707L,
89578 56708L,56709L,56710L,56711L,56712L,56713L,56714L,56715L,56716L,56717L,
89579 56718L,56719L,56720L,56721L,56722L,56723L,56724L,56725L,56726L,56727L,
89580 56728L,56729L,56730L,56731L,56732L,56733L,56734L,56735L,56736L,56737L,
89581 56738L,56739L,56740L,56741L,56742L,56743L,56744L,56745L,56746L,56747L,
89582 56748L,56749L,56750L,56751L,56752L,56753L,56754L,56755L,56756L,56757L,
89583 56758L,56759L,56760L,56761L,56762L,56763L,56764L,56765L,56766L,56767L,
89584 56768L,56769L,56770L,56771L,56772L,56773L,56774L,56775L,56776L,56777L,
89585 56778L,56779L,56780L,56781L,56782L,56783L,56784L,56785L,56786L,56787L,
89586 56788L,56789L,56790L,56791L,56792L,56793L,56794L,56795L,56796L,56797L,
89587 56798L,56799L,56800L,56801L,56802L,56803L,56804L,56805L,56806L,56807L,
89588 56808L,56809L,56810L,56811L,56812L,56813L,56814L,56815L,56816L,56817L,
89589 56818L,56819L,56820L,56821L,56822L,56823L,56824L,56825L,56826L,56827L,
89590 56828L,56829L,56830L,56831L,56832L,56833L,56834L,56835L,56836L,56837L,
89591 56838L,56839L,56840L,56841L,56842L,56843L,56844L,56845L,56846L,56847L,
89592 56848L,56849L,56850L,56851L,56852L,56853L,56854L,56855L,56856L,56857L,
89593 56858L,56859L,56860L,56861L,56862L,56863L,56864L,56865L,56866L,56867L,
89594 56868L,56869L,56870L,56871L,56872L,56873L,56874L,56875L,56876L,56877L,
89595 56878L,56879L,56880L,56881L,56882L,56883L,56884L,56885L,56886L,56887L,
89596 56888L,56889L,56890L,56891L,56892L,56893L,56894L,56895L,56896L,56897L,
89597 56898L,56899L,56900L,56901L,56902L,56903L,56904L,56905L,56906L,56907L,
89598 56908L,56909L,56910L,56911L,56912L,56913L,56914L,56915L,56916L,56917L,
89599 56918L,56919L,56920L,56921L,56922L,56923L,56924L,56925L,56926L,56927L,
89600 56928L,56929L,56930L,56931L,56932L,56933L,56934L,56935L,56936L,56937L,
89601 56938L,56939L,56940L,56941L,56942L,56943L,56944L,56945L,56946L,56947L,
89602 56948L,56949L,56950L,56951L,56952L,56953L,56954L,56955L,56956L,56957L,
89603 56958L,56959L,56960L,56961L,56962L,56963L,56964L,56965L,56966L,56967L,
89604 56968L,56969L,56970L,56971L,56972L,56973L,56974L,56975L,56976L,56977L,
89605 56978L,56979L,56980L,56981L,56982L,56983L,56984L,56985L,56986L,56987L,
89606 56988L,56989L,56990L,56991L,56992L,56993L,56994L,56995L,56996L,56997L,
89607 56998L,56999L,57000L,57001L,57002L,57003L,57004L,57005L,57006L,57007L,
89608 57008L,57009L,57010L,57011L,57012L,57013L,57014L,57015L,57016L,57017L,
89609 57018L,57019L,57020L,57021L,57022L,57023L,57024L,57025L,57026L,57027L,
89610 57028L,57029L,57030L,57031L,57032L,57033L,57034L,57035L,57036L,57037L,
89611 57038L,57039L,57040L,57041L,57042L,57043L,57044L,57045L,57046L,57047L,
89612 57048L,57049L,57050L,57051L,57052L,57053L,57054L,57055L,57056L,57057L,
89613 57058L,57059L,57060L,57061L,57062L,57063L,57064L,57065L,57066L,57067L,
89614 57068L,57069L,57070L,57071L,57072L,57073L,57074L,57075L,57076L,57077L,
89615 57078L,57079L,57080L,57081L,57082L,57083L,57084L,57085L,57086L,57087L,
89616 57088L,57089L,57090L,57091L,57092L,57093L,57094L,57095L,57096L,57097L,
89617 57098L,57099L,57100L,57101L,57102L,57103L,57104L,57105L,57106L,57107L,
89618 57108L,57109L,57110L,57111L,57112L,57113L,57114L,57115L,57116L,57117L,
89619 57118L,57119L,57120L,57121L,57122L,57123L,57124L,57125L,57126L,57127L,
89620 57128L,57129L,57130L,57131L,57132L,57133L,57134L,57135L,57136L,57137L,
89621 57138L,57139L,57140L,57141L,57142L,57143L,57144L,57145L,57146L,57147L,
89622 57148L,57149L,57150L,57151L,57152L,57153L,57154L,57155L,57156L,57157L,
89623 57158L,57159L,57160L,57161L,57162L,57163L,57164L,57165L,57166L,57167L,
89624 57168L,57169L,57170L,57171L,57172L,57173L,57174L,57175L,57176L,57177L,
89625 57178L,57179L,57180L,57181L,57182L,57183L,57184L,57185L,57186L,57187L,
89626 57188L,57189L,57190L,57191L,57192L,57193L,57194L,57195L,57196L,57197L,
89627 57198L,57199L,57200L,57201L,57202L,57203L,57204L,57205L,57206L,57207L,
89628 57208L,57209L,57210L,57211L,57212L,57213L,57214L,57215L,57216L,57217L,
89629 57218L,57219L,57220L,57221L,57222L,57223L,57224L,57225L,57226L,57227L,
89630 57228L,57229L,57230L,57231L,57232L,57233L,57234L,57235L,57236L,57237L,
89631 57238L,57239L,57240L,57241L,57242L,57243L,57244L,57245L,57246L,57247L,
89632 57248L,57249L,57250L,57251L,57252L,57253L,57254L,57255L,57256L,57257L,
89633 57258L,57259L,57260L,57261L,57262L,57263L,57264L,57265L,57266L,57267L,
89634 57268L,57269L,57270L,57271L,57272L,57273L,57274L,57275L,57276L,57277L,
89635 57278L,57279L,57280L,57281L,57282L,57283L,57284L,57285L,57286L,57287L,
89636 57288L,57289L,57290L,57291L,57292L,57293L,57294L,57295L,57296L,57297L,
89637 57298L,57299L,57300L,57301L,57302L,57303L,57304L,57305L,57306L,57307L,
89638 57308L,57309L,57310L,57311L,57312L,57313L,57314L,57315L,57316L,57317L,
89639 57318L,57319L,57320L,57321L,57322L,57323L,57324L,57325L,57326L,57327L,
89640 57328L,57329L,57330L,57331L,57332L,57333L,57334L,57335L,57336L,57337L,
89641 57338L,57339L,57340L,57341L,57342L,57343L,57344L,57345L,57346L,57347L,
89642 57348L,57349L,57350L,57351L,57352L,57353L,57354L,57355L,57356L,57357L,
89643 57358L,57359L,57360L,57361L,57362L,57363L,57364L,57365L,57366L,57367L,
89644 57368L,57369L,57370L,57371L,57372L,57373L,57374L,57375L,57376L,57377L,
89645 57378L,57379L,57380L,57381L,57382L,57383L,57384L,57385L,57386L,57387L,
89646 57388L,57389L,57390L,57391L,57392L,57393L,57394L,57395L,57396L,57397L,
89647 57398L,57399L,57400L,57401L,57402L,57403L,57404L,57405L,57406L,57407L,
89648 57408L,57409L,57410L,57411L,57412L,57413L,57414L,57415L,57416L,57417L,
89649 57418L,57419L,57420L,57421L,57422L,57423L,57424L,57425L,57426L,57427L,
89650 57428L,57429L,57430L,57431L,57432L,57433L,57434L,57435L,57436L,57437L,
89651 57438L,57439L,57440L,57441L,57442L,57443L,57444L,57445L,57446L,57447L,
89652 57448L,57449L,57450L,57451L,57452L,57453L,57454L,57455L,57456L,57457L,
89653 57458L,57459L,57460L,57461L,57462L,57463L,57464L,57465L,57466L,57467L,
89654 57468L,57469L,57470L,57471L,57472L,57473L,57474L,57475L,57476L,57477L,
89655 57478L,57479L,57480L,57481L,57482L,57483L,57484L,57485L,57486L,57487L,
89656 57488L,57489L,57490L,57491L,57492L,57493L,57494L,57495L,57496L,57497L,
89657 57498L,57499L,57500L,57501L,57502L,57503L,57504L,57505L,57506L,57507L,
89658 57508L,57509L,57510L,57511L,57512L,57513L,57514L,57515L,57516L,57517L,
89659 57518L,57519L,57520L,57521L,57522L,57523L,57524L,57525L,57526L,57527L,
89660 57528L,57529L,57530L,57531L,57532L,57533L,57534L,57535L,57536L,57537L,
89661 57538L,57539L,57540L,57541L,57542L,57543L,57544L,57545L,57546L,57547L,
89662 57548L,57549L,57550L,57551L,57552L,57553L,57554L,57555L,57556L,57557L,
89663 57558L,57559L,57560L,57561L,57562L,57563L,57564L,57565L,57566L,57567L,
89664 57568L,57569L,57570L,57571L,57572L,57573L,57574L,57575L,57576L,57577L,
89665 57578L,57579L,57580L,57581L,57582L,57583L,57584L,57585L,57586L,57587L,
89666 57588L,57589L,57590L,57591L,57592L,57593L,57594L,57595L,57596L,57597L,
89667 57598L,57599L,57600L,57601L,57602L,57603L,57604L,57605L,57606L,57607L,
89668 57608L,57609L,57610L,57611L,57612L,57613L,57614L,57615L,57616L,57617L,
89669 57618L,57619L,57620L,57621L,57622L,57623L,57624L,57625L,57626L,57627L,
89670 57628L,57629L,57630L,57631L,57632L,57633L,57634L,57635L,57636L,57637L,
89671 57638L,57639L,57640L,57641L,57642L,57643L,57644L,57645L,57646L,57647L,
89672 57648L,57649L,57650L,57651L,57652L,57653L,57654L,57655L,57656L,57657L,
89673 57658L,57659L,57660L,57661L,57662L,57663L,57664L,57665L,57666L,57667L,
89674 57668L,57669L,57670L,57671L,57672L,57673L,57674L,57675L,57676L,57677L,
89675 57678L,57679L,57680L,57681L,57682L,57683L,57684L,57685L,57686L,57687L,
89676 57688L,57689L,57690L,57691L,57692L,57693L,57694L,57695L,57696L,57697L,
89677 57698L,57699L,57700L,57701L,57702L,57703L,57704L,57705L,57706L,57707L,
89678 57708L,57709L,57710L,57711L,57712L,57713L,57714L,57715L,57716L,57717L,
89679 57718L,57719L,57720L,57721L,57722L,57723L,57724L,57725L,57726L,57727L,
89680 57728L,57729L,57730L,57731L,57732L,57733L,57734L,57735L,57736L,57737L,
89681 57738L,57739L,57740L,57741L,57742L,57743L,57744L,57745L,57746L,57747L,
89682 57748L,57749L,57750L,57751L,57752L,57753L,57754L,57755L,57756L,57757L,
89683 57758L,57759L,57760L,57761L,57762L,57763L,57764L,57765L,57766L,57767L,
89684 57768L,57769L,57770L,57771L,57772L,57773L,57774L,57775L,57776L,57777L,
89685 57778L,57779L,57780L,57781L,57782L,57783L,57784L,57785L,57786L,57787L,
89686 57788L,57789L,57790L,57791L,57792L,57793L,57794L,57795L,57796L,57797L,
89687 57798L,57799L,57800L,57801L,57802L,57803L,57804L,57805L,57806L,57807L,
89688 57808L,57809L,57810L,57811L,57812L,57813L,57814L,57815L,57816L,57817L,
89689 57818L,57819L,57820L,57821L,57822L,57823L,57824L,57825L,57826L,57827L,
89690 57828L,57829L,57830L,57831L,57832L,57833L,57834L,57835L,57836L,57837L,
89691 57838L,57839L,57840L,57841L,57842L,57843L,57844L,57845L,57846L,57847L,
89692 57848L,57849L,57850L,57851L,57852L,57853L,57854L,57855L,57856L,57857L,
89693 57858L,57859L,57860L,57861L,57862L,57863L,57864L,57865L,57866L,57867L,
89694 57868L,57869L,57870L,57871L,57872L,57873L,57874L,57875L,57876L,57877L,
89695 57878L,57879L,57880L,57881L,57882L,57883L,57884L,57885L,57886L,57887L,
89696 57888L,57889L,57890L,57891L,57892L,57893L,57894L,57895L,57896L,57897L,
89697 57898L,57899L,57900L,57901L,57902L,57903L,57904L,57905L,57906L,57907L,
89698 57908L,57909L,57910L,57911L,57912L,57913L,57914L,57915L,57916L,57917L,
89699 57918L,57919L,57920L,57921L,57922L,57923L,57924L,57925L,57926L,57927L,
89700 57928L,57929L,57930L,57931L,57932L,57933L,57934L,57935L,57936L,57937L,
89701 57938L,57939L,57940L,57941L,57942L,57943L,57944L,57945L,57946L,57947L,
89702 57948L,57949L,57950L,57951L,57952L,57953L,57954L,57955L,57956L,57957L,
89703 57958L,57959L,57960L,57961L,57962L,57963L,57964L,57965L,57966L,57967L,
89704 57968L,57969L,57970L,57971L,57972L,57973L,57974L,57975L,57976L,57977L,
89705 57978L,57979L,57980L,57981L,57982L,57983L,57984L,57985L,57986L,57987L,
89706 57988L,57989L,57990L,57991L,57992L,57993L,57994L,57995L,57996L,57997L,
89707 57998L,57999L,58000L,58001L,58002L,58003L,58004L,58005L,58006L,58007L,
89708 58008L,58009L,58010L,58011L,58012L,58013L,58014L,58015L,58016L,58017L,
89709 58018L,58019L,58020L,58021L,58022L,58023L,58024L,58025L,58026L,58027L,
89710 58028L,58029L,58030L,58031L,58032L,58033L,58034L,58035L,58036L,58037L,
89711 58038L,58039L,58040L,58041L,58042L,58043L,58044L,58045L,58046L,58047L,
89712 58048L,58049L,58050L,58051L,58052L,58053L,58054L,58055L,58056L,58057L,
89713 58058L,58059L,58060L,58061L,58062L,58063L,58064L,58065L,58066L,58067L,
89714 58068L,58069L,58070L,58071L,58072L,58073L,58074L,58075L,58076L,58077L,
89715 58078L,58079L,58080L,58081L,58082L,58083L,58084L,58085L,58086L,58087L,
89716 58088L,58089L,58090L,58091L,58092L,58093L,58094L,58095L,58096L,58097L,
89717 58098L,58099L,58100L,58101L,58102L,58103L,58104L,58105L,58106L,58107L,
89718 58108L,58109L,58110L,58111L,58112L,58113L,58114L,58115L,58116L,58117L,
89719 58118L,58119L,58120L,58121L,58122L,58123L,58124L,58125L,58126L,58127L,
89720 58128L,58129L,58130L,58131L,58132L,58133L,58134L,58135L,58136L,58137L,
89721 58138L,58139L,58140L,58141L,58142L,58143L,58144L,58145L,58146L,58147L,
89722 58148L,58149L,58150L,58151L,58152L,58153L,58154L,58155L,58156L,58157L,
89723 58158L,58159L,58160L,58161L,58162L,58163L,58164L,58165L,58166L,58167L,
89724 58168L,58169L,58170L,58171L,58172L,58173L,58174L,58175L,58176L,58177L,
89725 58178L,58179L,58180L,58181L,58182L,58183L,58184L,58185L,58186L,58187L,
89726 58188L,58189L,58190L,58191L,58192L,58193L,58194L,58195L,58196L,58197L,
89727 58198L,58199L,58200L,58201L,58202L,58203L,58204L,58205L,58206L,58207L,
89728 58208L,58209L,58210L,58211L,58212L,58213L,58214L,58215L,58216L,58217L,
89729 58218L,58219L,58220L,58221L,58222L,58223L,58224L,58225L,58226L,58227L,
89730 58228L,58229L,58230L,58231L,58232L,58233L,58234L,58235L,58236L,58237L,
89731 58238L,58239L,58240L,58241L,58242L,58243L,58244L,58245L,58246L,58247L,
89732 58248L,58249L,58250L,58251L,58252L,58253L,58254L,58255L,58256L,58257L,
89733 58258L,58259L,58260L,58261L,58262L,58263L,58264L,58265L,58266L,58267L,
89734 58268L,58269L,58270L,58271L,58272L,58273L,58274L,58275L,58276L,58277L,
89735 58278L,58279L,58280L,58281L,58282L,58283L,58284L,58285L,58286L,58287L,
89736 58288L,58289L,58290L,58291L,58292L,58293L,58294L,58295L,58296L,58297L,
89737 58298L,58299L,58300L,58301L,58302L,58303L,58304L,58305L,58306L,58307L,
89738 58308L,58309L,58310L,58311L,58312L,58313L,58314L,58315L,58316L,58317L,
89739 58318L,58319L,58320L,58321L,58322L,58323L,58324L,58325L,58326L,58327L,
89740 58328L,58329L,58330L,58331L,58332L,58333L,58334L,58335L,58336L,58337L,
89741 58338L,58339L,58340L,58341L,58342L,58343L,58344L,58345L,58346L,58347L,
89742 58348L,58349L,58350L,58351L,58352L,58353L,58354L,58355L,58356L,58357L,
89743 58358L,58359L,58360L,58361L,58362L,58363L,58364L,58365L,58366L,58367L,
89744 58368L,58369L,58370L,58371L,58372L,58373L,58374L,58375L,58376L,58377L,
89745 58378L,58379L,58380L,58381L,58382L,58383L,58384L,58385L,58386L,58387L,
89746 58388L,58389L,58390L,58391L,58392L,58393L,58394L,58395L,58396L,58397L,
89747 58398L,58399L,58400L,58401L,58402L,58403L,58404L,58405L,58406L,58407L,
89748 58408L,58409L,58410L,58411L,58412L,58413L,58414L,58415L,58416L,58417L,
89749 58418L,58419L,58420L,58421L,58422L,58423L,58424L,58425L,58426L,58427L,
89750 58428L,58429L,58430L,58431L,58432L,58433L,58434L,58435L,58436L,58437L,
89751 58438L,58439L,58440L,58441L,58442L,58443L,58444L,58445L,58446L,58447L,
89752 58448L,58449L,58450L,58451L,58452L,58453L,58454L,58455L,58456L,58457L,
89753 58458L,58459L,58460L,58461L,58462L,58463L,58464L,58465L,58466L,58467L,
89754 58468L,58469L,58470L,58471L,58472L,58473L,58474L,58475L,58476L,58477L,
89755 58478L,58479L,58480L,58481L,58482L,58483L,58484L,58485L,58486L,58487L,
89756 58488L,58489L,58490L,58491L,58492L,58493L,58494L,58495L,58496L,58497L,
89757 58498L,58499L,58500L,58501L,58502L,58503L,58504L,58505L,58506L,58507L,
89758 58508L,58509L,58510L,58511L,58512L,58513L,58514L,58515L,58516L,58517L,
89759 58518L,58519L,58520L,58521L,58522L,58523L,58524L,58525L,58526L,58527L,
89760 58528L,58529L,58530L,58531L,58532L,58533L,58534L,58535L,58536L,58537L,
89761 58538L,58539L,58540L,58541L,58542L,58543L,58544L,58545L,58546L,58547L,
89762 58548L,58549L,58550L,58551L,58552L,58553L,58554L,58555L,58556L,58557L,
89763 58558L,58559L,58560L,58561L,58562L,58563L,58564L,58565L,58566L,58567L,
89764 58568L,58569L,58570L,58571L,58572L,58573L,58574L,58575L,58576L,58577L,
89765 58578L,58579L,58580L,58581L,58582L,58583L,58584L,58585L,58586L,58587L,
89766 58588L,58589L,58590L,58591L,58592L,58593L,58594L,58595L,58596L,58597L,
89767 58598L,58599L,58600L,58601L,58602L,58603L,58604L,58605L,58606L,58607L,
89768 58608L,58609L,58610L,58611L,58612L,58613L,58614L,58615L,58616L,58617L,
89769 58618L,58619L,58620L,58621L,58622L,58623L,58624L,58625L,58626L,58627L,
89770 58628L,58629L,58630L,58631L,58632L,58633L,58634L,58635L,58636L,58637L,
89771 58638L,58639L,58640L,58641L,58642L,58643L,58644L,58645L,58646L,58647L,
89772 58648L,58649L,58650L,58651L,58652L,58653L,58654L,58655L,58656L,58657L,
89773 58658L,58659L,58660L,58661L,58662L,58663L,58664L,58665L,58666L,58667L,
89774 58668L,58669L,58670L,58671L,58672L,58673L,58674L,58675L,58676L,58677L,
89775 58678L,58679L,58680L,58681L,58682L,58683L,58684L,58685L,58686L,58687L,
89776 58688L,58689L,58690L,58691L,58692L,58693L,58694L,58695L,58696L,58697L,
89777 58698L,58699L,58700L,58701L,58702L,58703L,58704L,58705L,58706L,58707L,
89778 58708L,58709L,58710L,58711L,58712L,58713L,58714L,58715L,58716L,58717L,
89779 58718L,58719L,58720L,58721L,58722L,58723L,58724L,58725L,58726L,58727L,
89780 58728L,58729L,58730L,58731L,58732L,58733L,58734L,58735L,58736L,58737L,
89781 58738L,58739L,58740L,58741L,58742L,58743L,58744L,58745L,58746L,58747L,
89782 58748L,58749L,58750L,58751L,58752L,58753L,58754L,58755L,58756L,58757L,
89783 58758L,58759L,58760L,58761L,58762L,58763L,58764L,58765L,58766L,58767L,
89784 58768L,58769L,58770L,58771L,58772L,58773L,58774L,58775L,58776L,58777L,
89785 58778L,58779L,58780L,58781L,58782L,58783L,58784L,58785L,58786L,58787L,
89786 58788L,58789L,58790L,58791L,58792L,58793L,58794L,58795L,58796L,58797L,
89787 58798L,58799L,58800L,58801L,58802L,58803L,58804L,58805L,58806L,58807L,
89788 58808L,58809L,58810L,58811L,58812L,58813L,58814L,58815L,58816L,58817L,
89789 58818L,58819L,58820L,58821L,58822L,58823L,58824L,58825L,58826L,58827L,
89790 58828L,58829L,58830L,58831L,58832L,58833L,58834L,58835L,58836L,58837L,
89791 58838L,58839L,58840L,58841L,58842L,58843L,58844L,58845L,58846L,58847L,
89792 58848L,58849L,58850L,58851L,58852L,58853L,58854L,58855L,58856L,58857L,
89793 58858L,58859L,58860L,58861L,58862L,58863L,58864L,58865L,58866L,58867L,
89794 58868L,58869L,58870L,58871L,58872L,58873L,58874L,58875L,58876L,58877L,
89795 58878L,58879L,58880L,58881L,58882L,58883L,58884L,58885L,58886L,58887L,
89796 58888L,58889L,58890L,58891L,58892L,58893L,58894L,58895L,58896L,58897L,
89797 58898L,58899L,58900L,58901L,58902L,58903L,58904L,58905L,58906L,58907L,
89798 58908L,58909L,58910L,58911L,58912L,58913L,58914L,58915L,58916L,58917L,
89799 58918L,58919L,58920L,58921L,58922L,58923L,58924L,58925L,58926L,58927L,
89800 58928L,58929L,58930L,58931L,58932L,58933L,58934L,58935L,58936L,58937L,
89801 58938L,58939L,58940L,58941L,58942L,58943L,58944L,58945L,58946L,58947L,
89802 58948L,58949L,58950L,58951L,58952L,58953L,58954L,58955L,58956L,58957L,
89803 58958L,58959L,58960L,58961L,58962L,58963L,58964L,58965L,58966L,58967L,
89804 58968L,58969L,58970L,58971L,58972L,58973L,58974L,58975L,58976L,58977L,
89805 58978L,58979L,58980L,58981L,58982L,58983L,58984L,58985L,58986L,58987L,
89806 58988L,58989L,58990L,58991L,58992L,58993L,58994L,58995L,58996L,58997L,
89807 58998L,58999L,59000L,59001L,59002L,59003L,59004L,59005L,59006L,59007L,
89808 59008L,59009L,59010L,59011L,59012L,59013L,59014L,59015L,59016L,59017L,
89809 59018L,59019L,59020L,59021L,59022L,59023L,59024L,59025L,59026L,59027L,
89810 59028L,59029L,59030L,59031L,59032L,59033L,59034L,59035L,59036L,59037L,
89811 59038L,59039L,59040L,59041L,59042L,59043L,59044L,59045L,59046L,59047L,
89812 59048L,59049L,59050L,59051L,59052L,59053L,59054L,59055L,59056L,59057L,
89813 59058L,59059L,59060L,59061L,59062L,59063L,59064L,59065L,59066L,59067L,
89814 59068L,59069L,59070L,59071L,59072L,59073L,59074L,59075L,59076L,59077L,
89815 59078L,59079L,59080L,59081L,59082L,59083L,59084L,59085L,59086L,59087L,
89816 59088L,59089L,59090L,59091L,59092L,59093L,59094L,59095L,59096L,59097L,
89817 59098L,59099L,59100L,59101L,59102L,59103L,59104L,59105L,59106L,59107L,
89818 59108L,59109L,59110L,59111L,59112L,59113L,59114L,59115L,59116L,59117L,
89819 59118L,59119L,59120L,59121L,59122L,59123L,59124L,59125L,59126L,59127L,
89820 59128L,59129L,59130L,59131L,59132L,59133L,59134L,59135L,59136L,59137L,
89821 59138L,59139L,59140L,59141L,59142L,59143L,59144L,59145L,59146L,59147L,
89822 59148L,59149L,59150L,59151L,59152L,59153L,59154L,59155L,59156L,59157L,
89823 59158L,59159L,59160L,59161L,59162L,59163L,59164L,59165L,59166L,59167L,
89824 59168L,59169L,59170L,59171L,59172L,59173L,59174L,59175L,59176L,59177L,
89825 59178L,59179L,59180L,59181L,59182L,59183L,59184L,59185L,59186L,59187L,
89826 59188L,59189L,59190L,59191L,59192L,59193L,59194L,59195L,59196L,59197L,
89827 59198L,59199L,59200L,59201L,59202L,59203L,59204L,59205L,59206L,59207L,
89828 59208L,59209L,59210L,59211L,59212L,59213L,59214L,59215L,59216L,59217L,
89829 59218L,59219L,59220L,59221L,59222L,59223L,59224L,59225L,59226L,59227L,
89830 59228L,59229L,59230L,59231L,59232L,59233L,59234L,59235L,59236L,59237L,
89831 59238L,59239L,59240L,59241L,59242L,59243L,59244L,59245L,59246L,59247L,
89832 59248L,59249L,59250L,59251L,59252L,59253L,59254L,59255L,59256L,59257L,
89833 59258L,59259L,59260L,59261L,59262L,59263L,59264L,59265L,59266L,59267L,
89834 59268L,59269L,59270L,59271L,59272L,59273L,59274L,59275L,59276L,59277L,
89835 59278L,59279L,59280L,59281L,59282L,59283L,59284L,59285L,59286L,59287L,
89836 59288L,59289L,59290L,59291L,59292L,59293L,59294L,59295L,59296L,59297L,
89837 59298L,59299L,59300L,59301L,59302L,59303L,59304L,59305L,59306L,59307L,
89838 59308L,59309L,59310L,59311L,59312L,59313L,59314L,59315L,59316L,59317L,
89839 59318L,59319L,59320L,59321L,59322L,59323L,59324L,59325L,59326L,59327L,
89840 59328L,59329L,59330L,59331L,59332L,59333L,59334L,59335L,59336L,59337L,
89841 59338L,59339L,59340L,59341L,59342L,59343L,59344L,59345L,59346L,59347L,
89842 59348L,59349L,59350L,59351L,59352L,59353L,59354L,59355L,59356L,59357L,
89843 59358L,59359L,59360L,59361L,59362L,59363L,59364L,59365L,59366L,59367L,
89844 59368L,59369L,59370L,59371L,59372L,59373L,59374L,59375L,59376L,59377L,
89845 59378L,59379L,59380L,59381L,59382L,59383L,59384L,59385L,59386L,59387L,
89846 59388L,59389L,59390L,59391L,59392L,59393L,59394L,59395L,59396L,59397L,
89847 59398L,59399L,59400L,59401L,59402L,59403L,59404L,59405L,59406L,59407L,
89848 59408L,59409L,59410L,59411L,59412L,59413L,59414L,59415L,59416L,59417L,
89849 59418L,59419L,59420L,59421L,59422L,59423L,59424L,59425L,59426L,59427L,
89850 59428L,59429L,59430L,59431L,59432L,59433L,59434L,59435L,59436L,59437L,
89851 59438L,59439L,59440L,59441L,59442L,59443L,59444L,59445L,59446L,59447L,
89852 59448L,59449L,59450L,59451L,59452L,59453L,59454L,59455L,59456L,59457L,
89853 59458L,59459L,59460L,59461L,59462L,59463L,59464L,59465L,59466L,59467L,
89854 59468L,59469L,59470L,59471L,59472L,59473L,59474L,59475L,59476L,59477L,
89855 59478L,59479L,59480L,59481L,59482L,59483L,59484L,59485L,59486L,59487L,
89856 59488L,59489L,59490L,59491L,59492L,59493L,59494L,59495L,59496L,59497L,
89857 59498L,59499L,59500L,59501L,59502L,59503L,59504L,59505L,59506L,59507L,
89858 59508L,59509L,59510L,59511L,59512L,59513L,59514L,59515L,59516L,59517L,
89859 59518L,59519L,59520L,59521L,59522L,59523L,59524L,59525L,59526L,59527L,
89860 59528L,59529L,59530L,59531L,59532L,59533L,59534L,59535L,59536L,59537L,
89861 59538L,59539L,59540L,59541L,59542L,59543L,59544L,59545L,59546L,59547L,
89862 59548L,59549L,59550L,59551L,59552L,59553L,59554L,59555L,59556L,59557L,
89863 59558L,59559L,59560L,59561L,59562L,59563L,59564L,59565L,59566L,59567L,
89864 59568L,59569L,59570L,59571L,59572L,59573L,59574L,59575L,59576L,59577L,
89865 59578L,59579L,59580L,59581L,59582L,59583L,59584L,59585L,59586L,59587L,
89866 59588L,59589L,59590L,59591L,59592L,59593L,59594L,59595L,59596L,59597L,
89867 59598L,59599L,59600L,59601L,59602L,59603L,59604L,59605L,59606L,59607L,
89868 59608L,59609L,59610L,59611L,59612L,59613L,59614L,59615L,59616L,59617L,
89869 59618L,59619L,59620L,59621L,59622L,59623L,59624L,59625L,59626L,59627L,
89870 59628L,59629L,59630L,59631L,59632L,59633L,59634L,59635L,59636L,59637L,
89871 59638L,59639L,59640L,59641L,59642L,59643L,59644L,59645L,59646L,59647L,
89872 59648L,59649L,59650L,59651L,59652L,59653L,59654L,59655L,59656L,59657L,
89873 59658L,59659L,59660L,59661L,59662L,59663L,59664L,59665L,59666L,59667L,
89874 59668L,59669L,59670L,59671L,59672L,59673L,59674L,59675L,59676L,59677L,
89875 59678L,59679L,59680L,59681L,59682L,59683L,59684L,59685L,59686L,59687L,
89876 59688L,59689L,59690L,59691L,59692L,59693L,59694L,59695L,59696L,59697L,
89877 59698L,59699L,59700L,59701L,59702L,59703L,59704L,59705L,59706L,59707L,
89878 59708L,59709L,59710L,59711L,59712L,59713L,59714L,59715L,59716L,59717L,
89879 59718L,59719L,59720L,59721L,59722L,59723L,59724L,59725L,59726L,59727L,
89880 59728L,59729L,59730L,59731L,59732L,59733L,59734L,59735L,59736L,59737L,
89881 59738L,59739L,59740L,59741L,59742L,59743L,59744L,59745L,59746L,59747L,
89882 59748L,59749L,59750L,59751L,59752L,59753L,59754L,59755L,59756L,59757L,
89883 59758L,59759L,59760L,59761L,59762L,59763L,59764L,59765L,59766L,59767L,
89884 59768L,59769L,59770L,59771L,59772L,59773L,59774L,59775L,59776L,59777L,
89885 59778L,59779L,59780L,59781L,59782L,59783L,59784L,59785L,59786L,59787L,
89886 59788L,59789L,59790L,59791L,59792L,59793L,59794L,59795L,59796L,59797L,
89887 59798L,59799L,59800L,59801L,59802L,59803L,59804L,59805L,59806L,59807L,
89888 59808L,59809L,59810L,59811L,59812L,59813L,59814L,59815L,59816L,59817L,
89889 59818L,59819L,59820L,59821L,59822L,59823L,59824L,59825L,59826L,59827L,
89890 59828L,59829L,59830L,59831L,59832L,59833L,59834L,59835L,59836L,59837L,
89891 59838L,59839L,59840L,59841L,59842L,59843L,59844L,59845L,59846L,59847L,
89892 59848L,59849L,59850L,59851L,59852L,59853L,59854L,59855L,59856L,59857L,
89893 59858L,59859L,59860L,59861L,59862L,59863L,59864L,59865L,59866L,59867L,
89894 59868L,59869L,59870L,59871L,59872L,59873L,59874L,59875L,59876L,59877L,
89895 59878L,59879L,59880L,59881L,59882L,59883L,59884L,59885L,59886L,59887L,
89896 59888L,59889L,59890L,59891L,59892L,59893L,59894L,59895L,59896L,59897L,
89897 59898L,59899L,59900L,59901L,59902L,59903L,59904L,59905L,59906L,59907L,
89898 59908L,59909L,59910L,59911L,59912L,59913L,59914L,59915L,59916L,59917L,
89899 59918L,59919L,59920L,59921L,59922L,59923L,59924L,59925L,59926L,59927L,
89900 59928L,59929L,59930L,59931L,59932L,59933L,59934L,59935L,59936L,59937L,
89901 59938L,59939L,59940L,59941L,59942L,59943L,59944L,59945L,59946L,59947L,
89902 59948L,59949L,59950L,59951L,59952L,59953L,59954L,59955L,59956L,59957L,
89903 59958L,59959L,59960L,59961L,59962L,59963L,59964L,59965L,59966L,59967L,
89904 59968L,59969L,59970L,59971L,59972L,59973L,59974L,59975L,59976L,59977L,
89905 59978L,59979L,59980L,59981L,59982L,59983L,59984L,59985L,59986L,59987L,
89906 59988L,59989L,59990L,59991L,59992L,59993L,59994L,59995L,59996L,59997L,
89907 59998L,59999L,60000L,60001L,60002L,60003L,60004L,60005L,60006L,60007L,
89908 60008L,60009L,60010L,60011L,60012L,60013L,60014L,60015L,60016L,60017L,
89909 60018L,60019L,60020L,60021L,60022L,60023L,60024L,60025L,60026L,60027L,
89910 60028L,60029L,60030L,60031L,60032L,60033L,60034L,60035L,60036L,60037L,
89911 60038L,60039L,60040L,60041L,60042L,60043L,60044L,60045L,60046L,60047L,
89912 60048L,60049L,60050L,60051L,60052L,60053L,60054L,60055L,60056L,60057L,
89913 60058L,60059L,60060L,60061L,60062L,60063L,60064L,60065L,60066L,60067L,
89914 60068L,60069L,60070L,60071L,60072L,60073L,60074L,60075L,60076L,60077L,
89915 60078L,60079L,60080L,60081L,60082L,60083L,60084L,60085L,60086L,60087L,
89916 60088L,60089L,60090L,60091L,60092L,60093L,60094L,60095L,60096L,60097L,
89917 60098L,60099L,60100L,60101L,60102L,60103L,60104L,60105L,60106L,60107L,
89918 60108L,60109L,60110L,60111L,60112L,60113L,60114L,60115L,60116L,60117L,
89919 60118L,60119L,60120L,60121L,60122L,60123L,60124L,60125L,60126L,60127L,
89920 60128L,60129L,60130L,60131L,60132L,60133L,60134L,60135L,60136L,60137L,
89921 60138L,60139L,60140L,60141L,60142L,60143L,60144L,60145L,60146L,60147L,
89922 60148L,60149L,60150L,60151L,60152L,60153L,60154L,60155L,60156L,60157L,
89923 60158L,60159L,60160L,60161L,60162L,60163L,60164L,60165L,60166L,60167L,
89924 60168L,60169L,60170L,60171L,60172L,60173L,60174L,60175L,60176L,60177L,
89925 60178L,60179L,60180L,60181L,60182L,60183L,60184L,60185L,60186L,60187L,
89926 60188L,60189L,60190L,60191L,60192L,60193L,60194L,60195L,60196L,60197L,
89927 60198L,60199L,60200L,60201L,60202L,60203L,60204L,60205L,60206L,60207L,
89928 60208L,60209L,60210L,60211L,60212L,60213L,60214L,60215L,60216L,60217L,
89929 60218L,60219L,60220L,60221L,60222L,60223L,60224L,60225L,60226L,60227L,
89930 60228L,60229L,60230L,60231L,60232L,60233L,60234L,60235L,60236L,60237L,
89931 60238L,60239L,60240L,60241L,60242L,60243L,60244L,60245L,60246L,60247L,
89932 60248L,60249L,60250L,60251L,60252L,60253L,60254L,60255L,60256L,60257L,
89933 60258L,60259L,60260L,60261L,60262L,60263L,60264L,60265L,60266L,60267L,
89934 60268L,60269L,60270L,60271L,60272L,60273L,60274L,60275L,60276L,60277L,
89935 60278L,60279L,60280L,60281L,60282L,60283L,60284L,60285L,60286L,60287L,
89936 60288L,60289L,60290L,60291L,60292L,60293L,60294L,60295L,60296L,60297L,
89937 60298L,60299L,60300L,60301L,60302L,60303L,60304L,60305L,60306L,60307L,
89938 60308L,60309L,60310L,60311L,60312L,60313L,60314L,60315L,60316L,60317L,
89939 60318L,60319L,60320L,60321L,60322L,60323L,60324L,60325L,60326L,60327L,
89940 60328L,60329L,60330L,60331L,60332L,60333L,60334L,60335L,60336L,60337L,
89941 60338L,60339L,60340L,60341L,60342L,60343L,60344L,60345L,60346L,60347L,
89942 60348L,60349L,60350L,60351L,60352L,60353L,60354L,60355L,60356L,60357L,
89943 60358L,60359L,60360L,60361L,60362L,60363L,60364L,60365L,60366L,60367L,
89944 60368L,60369L,60370L,60371L,60372L,60373L,60374L,60375L,60376L,60377L,
89945 60378L,60379L,60380L,60381L,60382L,60383L,60384L,60385L,60386L,60387L,
89946 60388L,60389L,60390L,60391L,60392L,60393L,60394L,60395L,60396L,60397L,
89947 60398L,60399L,60400L,60401L,60402L,60403L,60404L,60405L,60406L,60407L,
89948 60408L,60409L,60410L,60411L,60412L,60413L,60414L,60415L,60416L,60417L,
89949 60418L,60419L,60420L,60421L,60422L,60423L,60424L,60425L,60426L,60427L,
89950 60428L,60429L,60430L,60431L,60432L,60433L,60434L,60435L,60436L,60437L,
89951 60438L,60439L,60440L,60441L,60442L,60443L,60444L,60445L,60446L,60447L,
89952 60448L,60449L,60450L,60451L,60452L,60453L,60454L,60455L,60456L,60457L,
89953 60458L,60459L,60460L,60461L,60462L,60463L,60464L,60465L,60466L,60467L,
89954 60468L,60469L,60470L,60471L,60472L,60473L,60474L,60475L,60476L,60477L,
89955 60478L,60479L,60480L,60481L,60482L,60483L,60484L,60485L,60486L,60487L,
89956 60488L,60489L,60490L,60491L,60492L,60493L,60494L,60495L,60496L,60497L,
89957 60498L,60499L,60500L,60501L,60502L,60503L,60504L,60505L,60506L,60507L,
89958 60508L,60509L,60510L,60511L,60512L,60513L,60514L,60515L,60516L,60517L,
89959 60518L,60519L,60520L,60521L,60522L,60523L,60524L,60525L,60526L,60527L,
89960 60528L,60529L,60530L,60531L,60532L,60533L,60534L,60535L,60536L,60537L,
89961 60538L,60539L,60540L,60541L,60542L,60543L,60544L,60545L,60546L,60547L,
89962 60548L,60549L,60550L,60551L,60552L,60553L,60554L,60555L,60556L,60557L,
89963 60558L,60559L,60560L,60561L,60562L,60563L,60564L,60565L,60566L,60567L,
89964 60568L,60569L,60570L,60571L,60572L,60573L,60574L,60575L,60576L,60577L,
89965 60578L,60579L,60580L,60581L,60582L,60583L,60584L,60585L,60586L,60587L,
89966 60588L,60589L,60590L,60591L,60592L,60593L,60594L,60595L,60596L,60597L,
89967 60598L,60599L,60600L,60601L,60602L,60603L,60604L,60605L,60606L,60607L,
89968 60608L,60609L,60610L,60611L,60612L,60613L,60614L,60615L,60616L,60617L,
89969 60618L,60619L,60620L,60621L,60622L,60623L,60624L,60625L,60626L,60627L,
89970 60628L,60629L,60630L,60631L,60632L,60633L,60634L,60635L,60636L,60637L,
89971 60638L,60639L,60640L,60641L,60642L,60643L,60644L,60645L,60646L,60647L,
89972 60648L,60649L,60650L,60651L,60652L,60653L,60654L,60655L,60656L,60657L,
89973 60658L,60659L,60660L,60661L,60662L,60663L,60664L,60665L,60666L,60667L,
89974 60668L,60669L,60670L,60671L,60672L,60673L,60674L,60675L,60676L,60677L,
89975 60678L,60679L,60680L,60681L,60682L,60683L,60684L,60685L,60686L,60687L,
89976 60688L,60689L,60690L,60691L,60692L,60693L,60694L,60695L,60696L,60697L,
89977 60698L,60699L,60700L,60701L,60702L,60703L,60704L,60705L,60706L,60707L,
89978 60708L,60709L,60710L,60711L,60712L,60713L,60714L,60715L,60716L,60717L,
89979 60718L,60719L,60720L,60721L,60722L,60723L,60724L,60725L,60726L,60727L,
89980 60728L,60729L,60730L,60731L,60732L,60733L,60734L,60735L,60736L,60737L,
89981 60738L,60739L,60740L,60741L,60742L,60743L,60744L,60745L,60746L,60747L,
89982 60748L,60749L,60750L,60751L,60752L,60753L,60754L,60755L,60756L,60757L,
89983 60758L,60759L,60760L,60761L,60762L,60763L,60764L,60765L,60766L,60767L,
89984 60768L,60769L,60770L,60771L,60772L,60773L,60774L,60775L,60776L,60777L,
89985 60778L,60779L,60780L,60781L,60782L,60783L,60784L,60785L,60786L,60787L,
89986 60788L,60789L,60790L,60791L,60792L,60793L,60794L,60795L,60796L,60797L,
89987 60798L,60799L,60800L,60801L,60802L,60803L,60804L,60805L,60806L,60807L,
89988 60808L,60809L,60810L,60811L,60812L,60813L,60814L,60815L,60816L,60817L,
89989 60818L,60819L,60820L,60821L,60822L,60823L,60824L,60825L,60826L,60827L,
89990 60828L,60829L,60830L,60831L,60832L,60833L,60834L,60835L,60836L,60837L,
89991 60838L,60839L,60840L,60841L,60842L,60843L,60844L,60845L,60846L,60847L,
89992 60848L,60849L,60850L,60851L,60852L,60853L,60854L,60855L,60856L,60857L,
89993 60858L,60859L,60860L,60861L,60862L,60863L,60864L,60865L,60866L,60867L,
89994 60868L,60869L,60870L,60871L,60872L,60873L,60874L,60875L,60876L,60877L,
89995 60878L,60879L,60880L,60881L,60882L,60883L,60884L,60885L,60886L,60887L,
89996 60888L,60889L,60890L,60891L,60892L,60893L,60894L,60895L,60896L,60897L,
89997 60898L,60899L,60900L,60901L,60902L,60903L,60904L,60905L,60906L,60907L,
89998 60908L,60909L,60910L,60911L,60912L,60913L,60914L,60915L,60916L,60917L,
89999 60918L,60919L,60920L,60921L,60922L,60923L,60924L,60925L,60926L,60927L,
90000 60928L,60929L,60930L,60931L,60932L,60933L,60934L,60935L,60936L,60937L,
90001 60938L,60939L,60940L,60941L,60942L,60943L,60944L,60945L,60946L,60947L,
90002 60948L,60949L,60950L,60951L,60952L,60953L,60954L,60955L,60956L,60957L,
90003 60958L,60959L,60960L,60961L,60962L,60963L,60964L,60965L,60966L,60967L,
90004 60968L,60969L,60970L,60971L,60972L,60973L,60974L,60975L,60976L,60977L,
90005 60978L,60979L,60980L,60981L,60982L,60983L,60984L,60985L,60986L,60987L,
90006 60988L,60989L,60990L,60991L,60992L,60993L,60994L,60995L,60996L,60997L,
90007 60998L,60999L,61000L,61001L,61002L,61003L,61004L,61005L,61006L,61007L,
90008 61008L,61009L,61010L,61011L,61012L,61013L,61014L,61015L,61016L,61017L,
90009 61018L,61019L,61020L,61021L,61022L,61023L,61024L,61025L,61026L,61027L,
90010 61028L,61029L,61030L,61031L,61032L,61033L,61034L,61035L,61036L,61037L,
90011 61038L,61039L,61040L,61041L,61042L,61043L,61044L,61045L,61046L,61047L,
90012 61048L,61049L,61050L,61051L,61052L,61053L,61054L,61055L,61056L,61057L,
90013 61058L,61059L,61060L,61061L,61062L,61063L,61064L,61065L,61066L,61067L,
90014 61068L,61069L,61070L,61071L,61072L,61073L,61074L,61075L,61076L,61077L,
90015 61078L,61079L,61080L,61081L,61082L,61083L,61084L,61085L,61086L,61087L,
90016 61088L,61089L,61090L,61091L,61092L,61093L,61094L,61095L,61096L,61097L,
90017 61098L,61099L,61100L,61101L,61102L,61103L,61104L,61105L,61106L,61107L,
90018 61108L,61109L,61110L,61111L,61112L,61113L,61114L,61115L,61116L,61117L,
90019 61118L,61119L,61120L,61121L,61122L,61123L,61124L,61125L,61126L,61127L,
90020 61128L,61129L,61130L,61131L,61132L,61133L,61134L,61135L,61136L,61137L,
90021 61138L,61139L,61140L,61141L,61142L,61143L,61144L,61145L,61146L,61147L,
90022 61148L,61149L,61150L,61151L,61152L,61153L,61154L,61155L,61156L,61157L,
90023 61158L,61159L,61160L,61161L,61162L,61163L,61164L,61165L,61166L,61167L,
90024 61168L,61169L,61170L,61171L,61172L,61173L,61174L,61175L,61176L,61177L,
90025 61178L,61179L,61180L,61181L,61182L,61183L,61184L,61185L,61186L,61187L,
90026 61188L,61189L,61190L,61191L,61192L,61193L,61194L,61195L,61196L,61197L,
90027 61198L,61199L,61200L,61201L,61202L,61203L,61204L,61205L,61206L,61207L,
90028 61208L,61209L,61210L,61211L,61212L,61213L,61214L,61215L,61216L,61217L,
90029 61218L,61219L,61220L,61221L,61222L,61223L,61224L,61225L,61226L,61227L,
90030 61228L,61229L,61230L,61231L,61232L,61233L,61234L,61235L,61236L,61237L,
90031 61238L,61239L,61240L,61241L,61242L,61243L,61244L,61245L,61246L,61247L,
90032 61248L,61249L,61250L,61251L,61252L,61253L,61254L,61255L,61256L,61257L,
90033 61258L,61259L,61260L,61261L,61262L,61263L,61264L,61265L,61266L,61267L,
90034 61268L,61269L,61270L,61271L,61272L,61273L,61274L,61275L,61276L,61277L,
90035 61278L,61279L,61280L,61281L,61282L,61283L,61284L,61285L,61286L,61287L,
90036 61288L,61289L,61290L,61291L,61292L,61293L,61294L,61295L,61296L,61297L,
90037 61298L,61299L,61300L,61301L,61302L,61303L,61304L,61305L,61306L,61307L,
90038 61308L,61309L,61310L,61311L,61312L,61313L,61314L,61315L,61316L,61317L,
90039 61318L,61319L,61320L,61321L,61322L,61323L,61324L,61325L,61326L,61327L,
90040 61328L,61329L,61330L,61331L,61332L,61333L,61334L,61335L,61336L,61337L,
90041 61338L,61339L,61340L,61341L,61342L,61343L,61344L,61345L,61346L,61347L,
90042 61348L,61349L,61350L,61351L,61352L,61353L,61354L,61355L,61356L,61357L,
90043 61358L,61359L,61360L,61361L,61362L,61363L,61364L,61365L,61366L,61367L,
90044 61368L,61369L,61370L,61371L,61372L,61373L,61374L,61375L,61376L,61377L,
90045 61378L,61379L,61380L,61381L,61382L,61383L,61384L,61385L,61386L,61387L,
90046 61388L,61389L,61390L,61391L,61392L,61393L,61394L,61395L,61396L,61397L,
90047 61398L,61399L,61400L,61401L,61402L,61403L,61404L,61405L,61406L,61407L,
90048 61408L,61409L,61410L,61411L,61412L,61413L,61414L,61415L,61416L,61417L,
90049 61418L,61419L,61420L,61421L,61422L,61423L,61424L,61425L,61426L,61427L,
90050 61428L,61429L,61430L,61431L,61432L,61433L,61434L,61435L,61436L,61437L,
90051 61438L,61439L,61440L,61441L,61442L,61443L,61444L,61445L,61446L,61447L,
90052 61448L,61449L,61450L,61451L,61452L,61453L,61454L,61455L,61456L,61457L,
90053 61458L,61459L,61460L,61461L,61462L,61463L,61464L,61465L,61466L,61467L,
90054 61468L,61469L,61470L,61471L,61472L,61473L,61474L,61475L,61476L,61477L,
90055 61478L,61479L,61480L,61481L,61482L,61483L,61484L,61485L,61486L,61487L,
90056 61488L,61489L,61490L,61491L,61492L,61493L,61494L,61495L,61496L,61497L,
90057 61498L,61499L,61500L,61501L,61502L,61503L,61504L,61505L,61506L,61507L,
90058 61508L,61509L,61510L,61511L,61512L,61513L,61514L,61515L,61516L,61517L,
90059 61518L,61519L,61520L,61521L,61522L,61523L,61524L,61525L,61526L,61527L,
90060 61528L,61529L,61530L,61531L,61532L,61533L,61534L,61535L,61536L,61537L,
90061 61538L,61539L,61540L,61541L,61542L,61543L,61544L,61545L,61546L,61547L,
90062 61548L,61549L,61550L,61551L,61552L,61553L,61554L,61555L,61556L,61557L,
90063 61558L,61559L,61560L,61561L,61562L,61563L,61564L,61565L,61566L,61567L,
90064 61568L,61569L,61570L,61571L,61572L,61573L,61574L,61575L,61576L,61577L,
90065 61578L,61579L,61580L,61581L,61582L,61583L,61584L,61585L,61586L,61587L,
90066 61588L,61589L,61590L,61591L,61592L,61593L,61594L,61595L,61596L,61597L,
90067 61598L,61599L,61600L,61601L,61602L,61603L,61604L,61605L,61606L,61607L,
90068 61608L,61609L,61610L,61611L,61612L,61613L,61614L,61615L,61616L,61617L,
90069 61618L,61619L,61620L,61621L,61622L,61623L,61624L,61625L,61626L,61627L,
90070 61628L,61629L,61630L,61631L,61632L,61633L,61634L,61635L,61636L,61637L,
90071 61638L,61639L,61640L,61641L,61642L,61643L,61644L,61645L,61646L,61647L,
90072 61648L,61649L,61650L,61651L,61652L,61653L,61654L,61655L,61656L,61657L,
90073 61658L,61659L,61660L,61661L,61662L,61663L,61664L,61665L,61666L,61667L,
90074 61668L,61669L,61670L,61671L,61672L,61673L,61674L,61675L,61676L,61677L,
90075 61678L,61679L,61680L,61681L,61682L,61683L,61684L,61685L,61686L,61687L,
90076 61688L,61689L,61690L,61691L,61692L,61693L,61694L,61695L,61696L,61697L,
90077 61698L,61699L,61700L,61701L,61702L,61703L,61704L,61705L,61706L,61707L,
90078 61708L,61709L,61710L,61711L,61712L,61713L,61714L,61715L,61716L,61717L,
90079 61718L,61719L,61720L,61721L,61722L,61723L,61724L,61725L,61726L,61727L,
90080 61728L,61729L,61730L,61731L,61732L,61733L,61734L,61735L,61736L,61737L,
90081 61738L,61739L,61740L,61741L,61742L,61743L,61744L,61745L,61746L,61747L,
90082 61748L,61749L,61750L,61751L,61752L,61753L,61754L,61755L,61756L,61757L,
90083 61758L,61759L,61760L,61761L,61762L,61763L,61764L,61765L,61766L,61767L,
90084 61768L,61769L,61770L,61771L,61772L,61773L,61774L,61775L,61776L,61777L,
90085 61778L,61779L,61780L,61781L,61782L,61783L,61784L,61785L,61786L,61787L,
90086 61788L,61789L,61790L,61791L,61792L,61793L,61794L,61795L,61796L,61797L,
90087 61798L,61799L,61800L,61801L,61802L,61803L,61804L,61805L,61806L,61807L,
90088 61808L,61809L,61810L,61811L,61812L,61813L,61814L,61815L,61816L,61817L,
90089 61818L,61819L,61820L,61821L,61822L,61823L,61824L,61825L,61826L,61827L,
90090 61828L,61829L,61830L,61831L,61832L,61833L,61834L,61835L,61836L,61837L,
90091 61838L,61839L,61840L,61841L,61842L,61843L,61844L,61845L,61846L,61847L,
90092 61848L,61849L,61850L,61851L,61852L,61853L,61854L,61855L,61856L,61857L,
90093 61858L,61859L,61860L,61861L,61862L,61863L,61864L,61865L,61866L,61867L,
90094 61868L,61869L,61870L,61871L,61872L,61873L,61874L,61875L,61876L,61877L,
90095 61878L,61879L,61880L,61881L,61882L,61883L,61884L,61885L,61886L,61887L,
90096 61888L,61889L,61890L,61891L,61892L,61893L,61894L,61895L,61896L,61897L,
90097 61898L,61899L,61900L,61901L,61902L,61903L,61904L,61905L,61906L,61907L,
90098 61908L,61909L,61910L,61911L,61912L,61913L,61914L,61915L,61916L,61917L,
90099 61918L,61919L,61920L,61921L,61922L,61923L,61924L,61925L,61926L,61927L,
90100 61928L,61929L,61930L,61931L,61932L,61933L,61934L,61935L,61936L,61937L,
90101 61938L,61939L,61940L,61941L,61942L,61943L,61944L,61945L,61946L,61947L,
90102 61948L,61949L,61950L,61951L,61952L,61953L,61954L,61955L,61956L,61957L,
90103 61958L,61959L,61960L,61961L,61962L,61963L,61964L,61965L,61966L,61967L,
90104 61968L,61969L,61970L,61971L,61972L,61973L,61974L,61975L,61976L,61977L,
90105 61978L,61979L,61980L,61981L,61982L,61983L,61984L,61985L,61986L,61987L,
90106 61988L,61989L,61990L,61991L,61992L,61993L,61994L,61995L,61996L,61997L,
90107 61998L,61999L,62000L,62001L,62002L,62003L,62004L,62005L,62006L,62007L,
90108 62008L,62009L,62010L,62011L,62012L,62013L,62014L,62015L,62016L,62017L,
90109 62018L,62019L,62020L,62021L,62022L,62023L,62024L,62025L,62026L,62027L,
90110 62028L,62029L,62030L,62031L,62032L,62033L,62034L,62035L,62036L,62037L,
90111 62038L,62039L,62040L,62041L,62042L,62043L,62044L,62045L,62046L,62047L,
90112 62048L,62049L,62050L,62051L,62052L,62053L,62054L,62055L,62056L,62057L,
90113 62058L,62059L,62060L,62061L,62062L,62063L,62064L,62065L,62066L,62067L,
90114 62068L,62069L,62070L,62071L,62072L,62073L,62074L,62075L,62076L,62077L,
90115 62078L,62079L,62080L,62081L,62082L,62083L,62084L,62085L,62086L,62087L,
90116 62088L,62089L,62090L,62091L,62092L,62093L,62094L,62095L,62096L,62097L,
90117 62098L,62099L,62100L,62101L,62102L,62103L,62104L,62105L,62106L,62107L,
90118 62108L,62109L,62110L,62111L,62112L,62113L,62114L,62115L,62116L,62117L,
90119 62118L,62119L,62120L,62121L,62122L,62123L,62124L,62125L,62126L,62127L,
90120 62128L,62129L,62130L,62131L,62132L,62133L,62134L,62135L,62136L,62137L,
90121 62138L,62139L,62140L,62141L,62142L,62143L,62144L,62145L,62146L,62147L,
90122 62148L,62149L,62150L,62151L,62152L,62153L,62154L,62155L,62156L,62157L,
90123 62158L,62159L,62160L,62161L,62162L,62163L,62164L,62165L,62166L,62167L,
90124 62168L,62169L,62170L,62171L,62172L,62173L,62174L,62175L,62176L,62177L,
90125 62178L,62179L,62180L,62181L,62182L,62183L,62184L,62185L,62186L,62187L,
90126 62188L,62189L,62190L,62191L,62192L,62193L,62194L,62195L,62196L,62197L,
90127 62198L,62199L,62200L,62201L,62202L,62203L,62204L,62205L,62206L,62207L,
90128 62208L,62209L,62210L,62211L,62212L,62213L,62214L,62215L,62216L,62217L,
90129 62218L,62219L,62220L,62221L,62222L,62223L,62224L,62225L,62226L,62227L,
90130 62228L,62229L,62230L,62231L,62232L,62233L,62234L,62235L,62236L,62237L,
90131 62238L,62239L,62240L,62241L,62242L,62243L,62244L,62245L,62246L,62247L,
90132 62248L,62249L,62250L,62251L,62252L,62253L,62254L,62255L,62256L,62257L,
90133 62258L,62259L,62260L,62261L,62262L,62263L,62264L,62265L,62266L,62267L,
90134 62268L,62269L,62270L,62271L,62272L,62273L,62274L,62275L,62276L,62277L,
90135 62278L,62279L,62280L,62281L,62282L,62283L,62284L,62285L,62286L,62287L,
90136 62288L,62289L,62290L,62291L,62292L,62293L,62294L,62295L,62296L,62297L,
90137 62298L,62299L,62300L,62301L,62302L,62303L,62304L,62305L,62306L,62307L,
90138 62308L,62309L,62310L,62311L,62312L,62313L,62314L,62315L,62316L,62317L,
90139 62318L,62319L,62320L,62321L,62322L,62323L,62324L,62325L,62326L,62327L,
90140 62328L,62329L,62330L,62331L,62332L,62333L,62334L,62335L,62336L,62337L,
90141 62338L,62339L,62340L,62341L,62342L,62343L,62344L,62345L,62346L,62347L,
90142 62348L,62349L,62350L,62351L,62352L,62353L,62354L,62355L,62356L,62357L,
90143 62358L,62359L,62360L,62361L,62362L,62363L,62364L,62365L,62366L,62367L,
90144 62368L,62369L,62370L,62371L,62372L,62373L,62374L,62375L,62376L,62377L,
90145 62378L,62379L,62380L,62381L,62382L,62383L,62384L,62385L,62386L,62387L,
90146 62388L,62389L,62390L,62391L,62392L,62393L,62394L,62395L,62396L,62397L,
90147 62398L,62399L,62400L,62401L,62402L,62403L,62404L,62405L,62406L,62407L,
90148 62408L,62409L,62410L,62411L,62412L,62413L,62414L,62415L,62416L,62417L,
90149 62418L,62419L,62420L,62421L,62422L,62423L,62424L,62425L,62426L,62427L,
90150 62428L,62429L,62430L,62431L,62432L,62433L,62434L,62435L,62436L,62437L,
90151 62438L,62439L,62440L,62441L,62442L,62443L,62444L,62445L,62446L,62447L,
90152 62448L,62449L,62450L,62451L,62452L,62453L,62454L,62455L,62456L,62457L,
90153 62458L,62459L,62460L,62461L,62462L,62463L,62464L,62465L,62466L,62467L,
90154 62468L,62469L,62470L,62471L,62472L,62473L,62474L,62475L,62476L,62477L,
90155 62478L,62479L,62480L,62481L,62482L,62483L,62484L,62485L,62486L,62487L,
90156 62488L,62489L,62490L,62491L,62492L,62493L,62494L,62495L,62496L,62497L,
90157 62498L,62499L,62500L,62501L,62502L,62503L,62504L,62505L,62506L,62507L,
90158 62508L,62509L,62510L,62511L,62512L,62513L,62514L,62515L,62516L,62517L,
90159 62518L,62519L,62520L,62521L,62522L,62523L,62524L,62525L,62526L,62527L,
90160 62528L,62529L,62530L,62531L,62532L,62533L,62534L,62535L,62536L,62537L,
90161 62538L,62539L,62540L,62541L,62542L,62543L,62544L,62545L,62546L,62547L,
90162 62548L,62549L,62550L,62551L,62552L,62553L,62554L,62555L,62556L,62557L,
90163 62558L,62559L,62560L,62561L,62562L,62563L,62564L,62565L,62566L,62567L,
90164 62568L,62569L,62570L,62571L,62572L,62573L,62574L,62575L,62576L,62577L,
90165 62578L,62579L,62580L,62581L,62582L,62583L,62584L,62585L,62586L,62587L,
90166 62588L,62589L,62590L,62591L,62592L,62593L,62594L,62595L,62596L,62597L,
90167 62598L,62599L,62600L,62601L,62602L,62603L,62604L,62605L,62606L,62607L,
90168 62608L,62609L,62610L,62611L,62612L,62613L,62614L,62615L,62616L,62617L,
90169 62618L,62619L,62620L,62621L,62622L,62623L,62624L,62625L,62626L,62627L,
90170 62628L,62629L,62630L,62631L,62632L,62633L,62634L,62635L,62636L,62637L,
90171 62638L,62639L,62640L,62641L,62642L,62643L,62644L,62645L,62646L,62647L,
90172 62648L,62649L,62650L,62651L,62652L,62653L,62654L,62655L,62656L,62657L,
90173 62658L,62659L,62660L,62661L,62662L,62663L,62664L,62665L,62666L,62667L,
90174 62668L,62669L,62670L,62671L,62672L,62673L,62674L,62675L,62676L,62677L,
90175 62678L,62679L,62680L,62681L,62682L,62683L,62684L,62685L,62686L,62687L,
90176 62688L,62689L,62690L,62691L,62692L,62693L,62694L,62695L,62696L,62697L,
90177 62698L,62699L,62700L,62701L,62702L,62703L,62704L,62705L,62706L,62707L,
90178 62708L,62709L,62710L,62711L,62712L,62713L,62714L,62715L,62716L,62717L,
90179 62718L,62719L,62720L,62721L,62722L,62723L,62724L,62725L,62726L,62727L,
90180 62728L,62729L,62730L,62731L,62732L,62733L,62734L,62735L,62736L,62737L,
90181 62738L,62739L,62740L,62741L,62742L,62743L,62744L,62745L,62746L,62747L,
90182 62748L,62749L,62750L,62751L,62752L,62753L,62754L,62755L,62756L,62757L,
90183 62758L,62759L,62760L,62761L,62762L,62763L,62764L,62765L,62766L,62767L,
90184 62768L,62769L,62770L,62771L,62772L,62773L,62774L,62775L,62776L,62777L,
90185 62778L,62779L,62780L,62781L,62782L,62783L,62784L,62785L,62786L,62787L,
90186 62788L,62789L,62790L,62791L,62792L,62793L,62794L,62795L,62796L,62797L,
90187 62798L,62799L,62800L,62801L,62802L,62803L,62804L,62805L,62806L,62807L,
90188 62808L,62809L,62810L,62811L,62812L,62813L,62814L,62815L,62816L,62817L,
90189 62818L,62819L,62820L,62821L,62822L,62823L,62824L,62825L,62826L,62827L,
90190 62828L,62829L,62830L,62831L,62832L,62833L,62834L,62835L,62836L,62837L,
90191 62838L,62839L,62840L,62841L,62842L,62843L,62844L,62845L,62846L,62847L,
90192 62848L,62849L,62850L,62851L,62852L,62853L,62854L,62855L,62856L,62857L,
90193 62858L,62859L,62860L,62861L,62862L,62863L,62864L,62865L,62866L,62867L,
90194 62868L,62869L,62870L,62871L,62872L,62873L,62874L,62875L,62876L,62877L,
90195 62878L,62879L,62880L,62881L,62882L,62883L,62884L,62885L,62886L,62887L,
90196 62888L,62889L,62890L,62891L,62892L,62893L,62894L,62895L,62896L,62897L,
90197 62898L,62899L,62900L,62901L,62902L,62903L,62904L,62905L,62906L,62907L,
90198 62908L,62909L,62910L,62911L,62912L,62913L,62914L,62915L,62916L,62917L,
90199 62918L,62919L,62920L,62921L,62922L,62923L,62924L,62925L,62926L,62927L,
90200 62928L,62929L,62930L,62931L,62932L,62933L,62934L,62935L,62936L,62937L,
90201 62938L,62939L,62940L,62941L,62942L,62943L,62944L,62945L,62946L,62947L,
90202 62948L,62949L,62950L,62951L,62952L,62953L,62954L,62955L,62956L,62957L,
90203 62958L,62959L,62960L,62961L,62962L,62963L,62964L,62965L,62966L,62967L,
90204 62968L,62969L,62970L,62971L,62972L,62973L,62974L,62975L,62976L,62977L,
90205 62978L,62979L,62980L,62981L,62982L,62983L,62984L,62985L,62986L,62987L,
90206 62988L,62989L,62990L,62991L,62992L,62993L,62994L,62995L,62996L,62997L,
90207 62998L,62999L,63000L,63001L,63002L,63003L,63004L,63005L,63006L,63007L,
90208 63008L,63009L,63010L,63011L,63012L,63013L,63014L,63015L,63016L,63017L,
90209 63018L,63019L,63020L,63021L,63022L,63023L,63024L,63025L,63026L,63027L,
90210 63028L,63029L,63030L,63031L,63032L,63033L,63034L,63035L,63036L,63037L,
90211 63038L,63039L,63040L,63041L,63042L,63043L,63044L,63045L,63046L,63047L,
90212 63048L,63049L,63050L,63051L,63052L,63053L,63054L,63055L,63056L,63057L,
90213 63058L,63059L,63060L,63061L,63062L,63063L,63064L,63065L,63066L,63067L,
90214 63068L,63069L,63070L,63071L,63072L,63073L,63074L,63075L,63076L,63077L,
90215 63078L,63079L,63080L,63081L,63082L,63083L,63084L,63085L,63086L,63087L,
90216 63088L,63089L,63090L,63091L,63092L,63093L,63094L,63095L,63096L,63097L,
90217 63098L,63099L,63100L,63101L,63102L,63103L,63104L,63105L,63106L,63107L,
90218 63108L,63109L,63110L,63111L,63112L,63113L,63114L,63115L,63116L,63117L,
90219 63118L,63119L,63120L,63121L,63122L,63123L,63124L,63125L,63126L,63127L,
90220 63128L,63129L,63130L,63131L,63132L,63133L,63134L,63135L,63136L,63137L,
90221 63138L,63139L,63140L,63141L,63142L,63143L,63144L,63145L,63146L,63147L,
90222 63148L,63149L,63150L,63151L,63152L,63153L,63154L,63155L,63156L,63157L,
90223 63158L,63159L,63160L,63161L,63162L,63163L,63164L,63165L,63166L,63167L,
90224 63168L,63169L,63170L,63171L,63172L,63173L,63174L,63175L,63176L,63177L,
90225 63178L,63179L,63180L,63181L,63182L,63183L,63184L,63185L,63186L,63187L,
90226 63188L,63189L,63190L,63191L,63192L,63193L,63194L,63195L,63196L,63197L,
90227 63198L,63199L,63200L,63201L,63202L,63203L,63204L,63205L,63206L,63207L,
90228 63208L,63209L,63210L,63211L,63212L,63213L,63214L,63215L,63216L,63217L,
90229 63218L,63219L,63220L,63221L,63222L,63223L,63224L,63225L,63226L,63227L,
90230 63228L,63229L,63230L,63231L,63232L,63233L,63234L,63235L,63236L,63237L,
90231 63238L,63239L,63240L,63241L,63242L,63243L,63244L,63245L,63246L,63247L,
90232 63248L,63249L,63250L,63251L,63252L,63253L,63254L,63255L,63256L,63257L,
90233 63258L,63259L,63260L,63261L,63262L,63263L,63264L,63265L,63266L,63267L,
90234 63268L,63269L,63270L,63271L,63272L,63273L,63274L,63275L,63276L,63277L,
90235 63278L,63279L,63280L,63281L,63282L,63283L,63284L,63285L,63286L,63287L,
90236 63288L,63289L,63290L,63291L,63292L,63293L,63294L,63295L,63296L,63297L,
90237 63298L,63299L,63300L,63301L,63302L,63303L,63304L,63305L,63306L,63307L,
90238 63308L,63309L,63310L,63311L,63312L,63313L,63314L,63315L,63316L,63317L,
90239 63318L,63319L,63320L,63321L,63322L,63323L,63324L,63325L,63326L,63327L,
90240 63328L,63329L,63330L,63331L,63332L,63333L,63334L,63335L,63336L,63337L,
90241 63338L,63339L,63340L,63341L,63342L,63343L,63344L,63345L,63346L,63347L,
90242 63348L,63349L,63350L,63351L,63352L,63353L,63354L,63355L,63356L,63357L,
90243 63358L,63359L,63360L,63361L,63362L,63363L,63364L,63365L,63366L,63367L,
90244 63368L,63369L,63370L,63371L,63372L,63373L,63374L,63375L,63376L,63377L,
90245 63378L,63379L,63380L,63381L,63382L,63383L,63384L,63385L,63386L,63387L,
90246 63388L,63389L,63390L,63391L,63392L,63393L,63394L,63395L,63396L,63397L,
90247 63398L,63399L,63400L,63401L,63402L,63403L,63404L,63405L,63406L,63407L,
90248 63408L,63409L,63410L,63411L,63412L,63413L,63414L,63415L,63416L,63417L,
90249 63418L,63419L,63420L,63421L,63422L,63423L,63424L,63425L,63426L,63427L,
90250 63428L,63429L,63430L,63431L,63432L,63433L,63434L,63435L,63436L,63437L,
90251 63438L,63439L,63440L,63441L,63442L,63443L,63444L,63445L,63446L,63447L,
90252 63448L,63449L,63450L,63451L,63452L,63453L,63454L,63455L,63456L,63457L,
90253 63458L,63459L,63460L,63461L,63462L,63463L,63464L,63465L,63466L,63467L,
90254 63468L,63469L,63470L,63471L,63472L,63473L,63474L,63475L,63476L,63477L,
90255 63478L,63479L,63480L,63481L,63482L,63483L,63484L,63485L,63486L,63487L,
90256 63488L,63489L,63490L,63491L,63492L,63493L,63494L,63495L,63496L,63497L,
90257 63498L,63499L,63500L,63501L,63502L,63503L,63504L,63505L,63506L,63507L,
90258 63508L,63509L,63510L,63511L,63512L,63513L,63514L,63515L,63516L,63517L,
90259 63518L,63519L,63520L,63521L,63522L,63523L,63524L,63525L,63526L,63527L,
90260 63528L,63529L,63530L,63531L,63532L,63533L,63534L,63535L,63536L,63537L,
90261 63538L,63539L,63540L,63541L,63542L,63543L,63544L,63545L,63546L,63547L,
90262 63548L,63549L,63550L,63551L,63552L,63553L,63554L,63555L,63556L,63557L,
90263 63558L,63559L,63560L,63561L,63562L,63563L,63564L,63565L,63566L,63567L,
90264 63568L,63569L,63570L,63571L,63572L,63573L,63574L,63575L,63576L,63577L,
90265 63578L,63579L,63580L,63581L,63582L,63583L,63584L,63585L,63586L,63587L,
90266 63588L,63589L,63590L,63591L,63592L,63593L,63594L,63595L,63596L,63597L,
90267 63598L,63599L,63600L,63601L,63602L,63603L,63604L,63605L,63606L,63607L,
90268 63608L,63609L,63610L,63611L,63612L,63613L,63614L,63615L,63616L,63617L,
90269 63618L,63619L,63620L,63621L,63622L,63623L,63624L,63625L,63626L,63627L,
90270 63628L,63629L,63630L,63631L,63632L,63633L,63634L,63635L,63636L,63637L,
90271 63638L,63639L,63640L,63641L,63642L,63643L,63644L,63645L,63646L,63647L,
90272 63648L,63649L,63650L,63651L,63652L,63653L,63654L,63655L,63656L,63657L,
90273 63658L,63659L,63660L,63661L,63662L,63663L,63664L,63665L,63666L,63667L,
90274 63668L,63669L,63670L,63671L,63672L,63673L,63674L,63675L,63676L,63677L,
90275 63678L,63679L,63680L,63681L,63682L,63683L,63684L,63685L,63686L,63687L,
90276 63688L,63689L,63690L,63691L,63692L,63693L,63694L,63695L,63696L,63697L,
90277 63698L,63699L,63700L,63701L,63702L,63703L,63704L,63705L,63706L,63707L,
90278 63708L,63709L,63710L,63711L,63712L,63713L,63714L,63715L,63716L,63717L,
90279 63718L,63719L,63720L,63721L,63722L,63723L,63724L,63725L,63726L,63727L,
90280 63728L,63729L,63730L,63731L,63732L,63733L,63734L,63735L,63736L,63737L,
90281 63738L,63739L,63740L,63741L,63742L,63743L,63744L,63745L,63746L,63747L,
90282 63748L,63749L,63750L,63751L,63752L,63753L,63754L,63755L,63756L,63757L,
90283 63758L,63759L,63760L,63761L,63762L,63763L,63764L,63765L,63766L,63767L,
90284 63768L,63769L,63770L,63771L,63772L,63773L,63774L,63775L,63776L,63777L,
90285 63778L,63779L,63780L,63781L,63782L,63783L,63784L,63785L,63786L,63787L,
90286 63788L,63789L,63790L,63791L,63792L,63793L,63794L,63795L,63796L,63797L,
90287 63798L,63799L,63800L,63801L,63802L,63803L,63804L,63805L,63806L,63807L,
90288 63808L,63809L,63810L,63811L,63812L,63813L,63814L,63815L,63816L,63817L,
90289 63818L,63819L,63820L,63821L,63822L,63823L,63824L,63825L,63826L,63827L,
90290 63828L,63829L,63830L,63831L,63832L,63833L,63834L,63835L,63836L,63837L,
90291 63838L,63839L,63840L,63841L,63842L,63843L,63844L,63845L,63846L,63847L,
90292 63848L,63849L,63850L,63851L,63852L,63853L,63854L,63855L,63856L,63857L,
90293 63858L,63859L,63860L,63861L,63862L,63863L,63864L,63865L,63866L,63867L,
90294 63868L,63869L,63870L,63871L,63872L,63873L,63874L,63875L,63876L,63877L,
90295 63878L,63879L,63880L,63881L,63882L,63883L,63884L,63885L,63886L,63887L,
90296 63888L,63889L,63890L,63891L,63892L,63893L,63894L,63895L,63896L,63897L,
90297 63898L,63899L,63900L,63901L,63902L,63903L,63904L,63905L,63906L,63907L,
90298 63908L,63909L,63910L,63911L,63912L,63913L,63914L,63915L,63916L,63917L,
90299 63918L,63919L,63920L,63921L,63922L,63923L,63924L,63925L,63926L,63927L,
90300 63928L,63929L,63930L,63931L,63932L,63933L,63934L,63935L,63936L,63937L,
90301 63938L,63939L,63940L,63941L,63942L,63943L,63944L,63945L,63946L,63947L,
90302 63948L,63949L,63950L,63951L,63952L,63953L,63954L,63955L,63956L,63957L,
90303 63958L,63959L,63960L,63961L,63962L,63963L,63964L,63965L,63966L,63967L,
90304 63968L,63969L,63970L,63971L,63972L,63973L,63974L,63975L,63976L,63977L,
90305 63978L,63979L,63980L,63981L,63982L,63983L,63984L,63985L,63986L,63987L,
90306 63988L,63989L,63990L,63991L,63992L,63993L,63994L,63995L,63996L,63997L,
90307 63998L,63999L,64000L,64001L,64002L,64003L,64004L,64005L,64006L,64007L,
90308 64008L,64009L,64010L,64011L,64012L,64013L,64014L,64015L,64016L,64017L,
90309 64018L,64019L,64020L,64021L,64022L,64023L,64024L,64025L,64026L,64027L,
90310 64028L,64029L,64030L,64031L,64032L,64033L,64034L,64035L,64036L,64037L,
90311 64038L,64039L,64040L,64041L,64042L,64043L,64044L,64045L,64046L,64047L,
90312 64048L,64049L,64050L,64051L,64052L,64053L,64054L,64055L,64056L,64057L,
90313 64058L,64059L,64060L,64061L,64062L,64063L,64064L,64065L,64066L,64067L,
90314 64068L,64069L,64070L,64071L,64072L,64073L,64074L,64075L,64076L,64077L,
90315 64078L,64079L,64080L,64081L,64082L,64083L,64084L,64085L,64086L,64087L,
90316 64088L,64089L,64090L,64091L,64092L,64093L,64094L,64095L,64096L,64097L,
90317 64098L,64099L,64100L,64101L,64102L,64103L,64104L,64105L,64106L,64107L,
90318 64108L,64109L,64110L,64111L,64112L,64113L,64114L,64115L,64116L,64117L,
90319 64118L,64119L,64120L,64121L,64122L,64123L,64124L,64125L,64126L,64127L,
90320 64128L,64129L,64130L,64131L,64132L,64133L,64134L,64135L,64136L,64137L,
90321 64138L,64139L,64140L,64141L,64142L,64143L,64144L,64145L,64146L,64147L,
90322 64148L,64149L,64150L,64151L,64152L,64153L,64154L,64155L,64156L,64157L,
90323 64158L,64159L,64160L,64161L,64162L,64163L,64164L,64165L,64166L,64167L,
90324 64168L,64169L,64170L,64171L,64172L,64173L,64174L,64175L,64176L,64177L,
90325 64178L,64179L,64180L,64181L,64182L,64183L,64184L,64185L,64186L,64187L,
90326 64188L,64189L,64190L,64191L,64192L,64193L,64194L,64195L,64196L,64197L,
90327 64198L,64199L,64200L,64201L,64202L,64203L,64204L,64205L,64206L,64207L,
90328 64208L,64209L,64210L,64211L,64212L,64213L,64214L,64215L,64216L,64217L,
90329 64218L,64219L,64220L,64221L,64222L,64223L,64224L,64225L,64226L,64227L,
90330 64228L,64229L,64230L,64231L,64232L,64233L,64234L,64235L,64236L,64237L,
90331 64238L,64239L,64240L,64241L,64242L,64243L,64244L,64245L,64246L,64247L,
90332 64248L,64249L,64250L,64251L,64252L,64253L,64254L,64255L,64256L,64257L,
90333 64258L,64259L,64260L,64261L,64262L,64263L,64264L,64265L,64266L,64267L,
90334 64268L,64269L,64270L,64271L,64272L,64273L,64274L,64275L,64276L,64277L,
90335 64278L,64279L,64280L,64281L,64282L,64283L,64284L,64285L,64286L,64287L,
90336 64288L,64289L,64290L,64291L,64292L,64293L,64294L,64295L,64296L,64297L,
90337 64298L,64299L,64300L,64301L,64302L,64303L,64304L,64305L,64306L,64307L,
90338 64308L,64309L,64310L,64311L,64312L,64313L,64314L,64315L,64316L,64317L,
90339 64318L,64319L,64320L,64321L,64322L,64323L,64324L,64325L,64326L,64327L,
90340 64328L,64329L,64330L,64331L,64332L,64333L,64334L,64335L,64336L,64337L,
90341 64338L,64339L,64340L,64341L,64342L,64343L,64344L,64345L,64346L,64347L,
90342 64348L,64349L,64350L,64351L,64352L,64353L,64354L,64355L,64356L,64357L,
90343 64358L,64359L,64360L,64361L,64362L,64363L,64364L,64365L,64366L,64367L,
90344 64368L,64369L,64370L,64371L,64372L,64373L,64374L,64375L,64376L,64377L,
90345 64378L,64379L,64380L,64381L,64382L,64383L,64384L,64385L,64386L,64387L,
90346 64388L,64389L,64390L,64391L,64392L,64393L,64394L,64395L,64396L,64397L,
90347 64398L,64399L,64400L,64401L,64402L,64403L,64404L,64405L,64406L,64407L,
90348 64408L,64409L,64410L,64411L,64412L,64413L,64414L,64415L,64416L,64417L,
90349 64418L,64419L,64420L,64421L,64422L,64423L,64424L,64425L,64426L,64427L,
90350 64428L,64429L,64430L,64431L,64432L,64433L,64434L,64435L,64436L,64437L,
90351 64438L,64439L,64440L,64441L,64442L,64443L,64444L,64445L,64446L,64447L,
90352 64448L,64449L,64450L,64451L,64452L,64453L,64454L,64455L,64456L,64457L,
90353 64458L,64459L,64460L,64461L,64462L,64463L,64464L,64465L,64466L,64467L,
90354 64468L,64469L,64470L,64471L,64472L,64473L,64474L,64475L,64476L,64477L,
90355 64478L,64479L,64480L,64481L,64482L,64483L,64484L,64485L,64486L,64487L,
90356 64488L,64489L,64490L,64491L,64492L,64493L,64494L,64495L,64496L,64497L,
90357 64498L,64499L,64500L,64501L,64502L,64503L,64504L,64505L,64506L,64507L,
90358 64508L,64509L,64510L,64511L,64512L,64513L,64514L,64515L,64516L,64517L,
90359 64518L,64519L,64520L,64521L,64522L,64523L,64524L,64525L,64526L,64527L,
90360 64528L,64529L,64530L,64531L,64532L,64533L,64534L,64535L,64536L,64537L,
90361 64538L,64539L,64540L,64541L,64542L,64543L,64544L,64545L,64546L,64547L,
90362 64548L,64549L,64550L,64551L,64552L,64553L,64554L,64555L,64556L,64557L,
90363 64558L,64559L,64560L,64561L,64562L,64563L,64564L,64565L,64566L,64567L,
90364 64568L,64569L,64570L,64571L,64572L,64573L,64574L,64575L,64576L,64577L,
90365 64578L,64579L,64580L,64581L,64582L,64583L,64584L,64585L,64586L,64587L,
90366 64588L,64589L,64590L,64591L,64592L,64593L,64594L,64595L,64596L,64597L,
90367 64598L,64599L,64600L,64601L,64602L,64603L,64604L,64605L,64606L,64607L,
90368 64608L,64609L,64610L,64611L,64612L,64613L,64614L,64615L,64616L,64617L,
90369 64618L,64619L,64620L,64621L,64622L,64623L,64624L,64625L,64626L,64627L,
90370 64628L,64629L,64630L,64631L,64632L,64633L,64634L,64635L,64636L,64637L,
90371 64638L,64639L,64640L,64641L,64642L,64643L,64644L,64645L,64646L,64647L,
90372 64648L,64649L,64650L,64651L,64652L,64653L,64654L,64655L,64656L,64657L,
90373 64658L,64659L,64660L,64661L,64662L,64663L,64664L,64665L,64666L,64667L,
90374 64668L,64669L,64670L,64671L,64672L,64673L,64674L,64675L,64676L,64677L,
90375 64678L,64679L,64680L,64681L,64682L,64683L,64684L,64685L,64686L,64687L,
90376 64688L,64689L,64690L,64691L,64692L,64693L,64694L,64695L,64696L,64697L,
90377 64698L,64699L,64700L,64701L,64702L,64703L,64704L,64705L,64706L,64707L,
90378 64708L,64709L,64710L,64711L,64712L,64713L,64714L,64715L,64716L,64717L,
90379 64718L,64719L,64720L,64721L,64722L,64723L,64724L,64725L,64726L,64727L,
90380 64728L,64729L,64730L,64731L,64732L,64733L,64734L,64735L,64736L,64737L,
90381 64738L,64739L,64740L,64741L,64742L,64743L,64744L,64745L,64746L,64747L,
90382 64748L,64749L,64750L,64751L,64752L,64753L,64754L,64755L,64756L,64757L,
90383 64758L,64759L,64760L,64761L,64762L,64763L,64764L,64765L,64766L,64767L,
90384 64768L,64769L,64770L,64771L,64772L,64773L,64774L,64775L,64776L,64777L,
90385 64778L,64779L,64780L,64781L,64782L,64783L,64784L,64785L,64786L,64787L,
90386 64788L,64789L,64790L,64791L,64792L,64793L,64794L,64795L,64796L,64797L,
90387 64798L,64799L,64800L,64801L,64802L,64803L,64804L,64805L,64806L,64807L,
90388 64808L,64809L,64810L,64811L,64812L,64813L,64814L,64815L,64816L,64817L,
90389 64818L,64819L,64820L,64821L,64822L,64823L,64824L,64825L,64826L,64827L,
90390 64828L,64829L,64830L,64831L,64832L,64833L,64834L,64835L,64836L,64837L,
90391 64838L,64839L,64840L,64841L,64842L,64843L,64844L,64845L,64846L,64847L,
90392 64848L,64849L,64850L,64851L,64852L,64853L,64854L,64855L,64856L,64857L,
90393 64858L,64859L,64860L,64861L,64862L,64863L,64864L,64865L,64866L,64867L,
90394 64868L,64869L,64870L,64871L,64872L,64873L,64874L,64875L,64876L,64877L,
90395 64878L,64879L,64880L,64881L,64882L,64883L,64884L,64885L,64886L,64887L,
90396 64888L,64889L,64890L,64891L,64892L,64893L,64894L,64895L,64896L,64897L,
90397 64898L,64899L,64900L,64901L,64902L,64903L,64904L,64905L,64906L,64907L,
90398 64908L,64909L,64910L,64911L,64912L,64913L,64914L,64915L,64916L,64917L,
90399 64918L,64919L,64920L,64921L,64922L,64923L,64924L,64925L,64926L,64927L,
90400 64928L,64929L,64930L,64931L,64932L,64933L,64934L,64935L,64936L,64937L,
90401 64938L,64939L,64940L,64941L,64942L,64943L,64944L,64945L,64946L,64947L,
90402 64948L,64949L,64950L,64951L,64952L,64953L,64954L,64955L,64956L,64957L,
90403 64958L,64959L,64960L,64961L,64962L,64963L,64964L,64965L,64966L,64967L,
90404 64968L,64969L,64970L,64971L,64972L,64973L,64974L,64975L,64976L,64977L,
90405 64978L,64979L,64980L,64981L,64982L,64983L,64984L,64985L,64986L,64987L,
90406 64988L,64989L,64990L,64991L,64992L,64993L,64994L,64995L,64996L,64997L,
90407 64998L,64999L,65000L,65001L,65002L,65003L,65004L,65005L,65006L,65007L,
90408 65008L,65009L,65010L,65011L,65012L,65013L,65014L,65015L,65016L,65017L,
90409 65018L,65019L,65020L,65021L,65022L,65023L,65024L,65025L,65026L,65027L,
90410 65028L,65029L,65030L,65031L,65032L,65033L,65034L,65035L,65036L,65037L,
90411 65038L,65039L,65040L,65041L,65042L,65043L,65044L,65045L,65046L,65047L,
90412 65048L,65049L,65050L,65051L,65052L,65053L,65054L,65055L,65056L,65057L,
90413 65058L,65059L,65060L,65061L,65062L,65063L,65064L,65065L,65066L,65067L,
90414 65068L,65069L,65070L,65071L,65072L,65073L,65074L,65075L,65076L,65077L,
90415 65078L,65079L,65080L,65081L,65082L,65083L,65084L,65085L,65086L,65087L,
90416 65088L,65089L,65090L,65091L,65092L,65093L,65094L,65095L,65096L,65097L,
90417 65098L,65099L,65100L,65101L,65102L,65103L,65104L,65105L,65106L,65107L,
90418 65108L,65109L,65110L,65111L,65112L,65113L,65114L,65115L,65116L,65117L,
90419 65118L,65119L,65120L,65121L,65122L,65123L,65124L,65125L,65126L,65127L,
90420 65128L,65129L,65130L,65131L,65132L,65133L,65134L,65135L,65136L,65137L,
90421 65138L,65139L,65140L,65141L,65142L,65143L,65144L,65145L,65146L,65147L,
90422 65148L,65149L,65150L,65151L,65152L,65153L,65154L,65155L,65156L,65157L,
90423 65158L,65159L,65160L,65161L,65162L,65163L,65164L,65165L,65166L,65167L,
90424 65168L,65169L,65170L,65171L,65172L,65173L,65174L,65175L,65176L,65177L,
90425 65178L,65179L,65180L,65181L,65182L,65183L,65184L,65185L,65186L,65187L,
90426 65188L,65189L,65190L,65191L,65192L,65193L,65194L,65195L,65196L,65197L,
90427 65198L,65199L,65200L,65201L,65202L,65203L,65204L,65205L,65206L,65207L,
90428 65208L,65209L,65210L,65211L,65212L,65213L,65214L,65215L,65216L,65217L,
90429 65218L,65219L,65220L,65221L,65222L,65223L,65224L,65225L,65226L,65227L,
90430 65228L,65229L,65230L,65231L,65232L,65233L,65234L,65235L,65236L,65237L,
90431 65238L,65239L,65240L,65241L,65242L,65243L,65244L,65245L,65246L,65247L,
90432 65248L,65249L,65250L,65251L,65252L,65253L,65254L,65255L,65256L,65257L,
90433 65258L,65259L,65260L,65261L,65262L,65263L,65264L,65265L,65266L,65267L,
90434 65268L,65269L,65270L,65271L,65272L,65273L,65274L,65275L,65276L,65277L,
90435 65278L,65279L,65280L,65281L,65282L,65283L,65284L,65285L,65286L,65287L,
90436 65288L,65289L,65290L,65291L,65292L,65293L,65294L,65295L,65296L,65297L,
90437 65298L,65299L,65300L,65301L,65302L,65303L,65304L,65305L,65306L,65307L,
90438 65308L,65309L,65310L,65311L,65312L,65313L,65314L,65315L,65316L,65317L,
90439 65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,65326L,65327L,
90440 65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,65336L,65337L,
90441 65338L,65339L,65340L,65341L,65342L,65343L,65344L,65313L,65314L,65315L,
90442 65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,
90443 65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,
90444 65336L,65337L,65338L,65371L,65372L,65373L,65374L,65375L,65376L,65377L,
90445 65378L,65379L,65380L,65381L,65382L,65383L,65384L,65385L,65386L,65387L,
90446 65388L,65389L,65390L,65391L,65392L,65393L,65394L,65395L,65396L,65397L,
90447 65398L,65399L,65400L,65401L,65402L,65403L,65404L,65405L,65406L,65407L,
90448 65408L,65409L,65410L,65411L,65412L,65413L,65414L,65415L,65416L,65417L,
90449 65418L,65419L,65420L,65421L,65422L,65423L,65424L,65425L,65426L,65427L,
90450 65428L,65429L,65430L,65431L,65432L,65433L,65434L,65435L,65436L,65437L,
90451 65438L,65439L,65440L,65441L,65442L,65443L,65444L,65445L,65446L,65447L,
90452 65448L,65449L,65450L,65451L,65452L,65453L,65454L,65455L,65456L,65457L,
90453 65458L,65459L,65460L,65461L,65462L,65463L,65464L,65465L,65466L,65467L,
90454 65468L,65469L,65470L,65471L,65472L,65473L,65474L,65475L,65476L,65477L,
90455 65478L,65479L,65480L,65481L,65482L,65483L,65484L,65485L,65486L,65487L,
90456 65488L,65489L,65490L,65491L,65492L,65493L,65494L,65495L,65496L,65497L,
90457 65498L,65499L,65500L,65501L,65502L,65503L,65504L,65505L,65506L,65507L,
90458 65508L,65509L,65510L,65511L,65512L,65513L,65514L,65515L,65516L,65517L,
90459 65518L,65519L,65520L,65521L,65522L,65523L,65524L,65525L,65526L,65527L,
90460 65528L,65529L,65530L,65531L,65532L,65533L,65534L,65535L,
90461 };
90462 #endif
90463 /*
90464  * Bitstream decoder.
90465  */
90466 
90467 /* #include duk_internal.h -> already included */
90468 
90469 /* Decode 'bits' bits from the input stream (bits must be 1...24).
90470  * When reading past bitstream end, zeroes are shifted in. The result
90471  * is signed to match duk_bd_decode_flagged.
90472  */
90473 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
90474  duk_small_int_t shift;
90475  duk_uint32_t mask;
90476  duk_uint32_t tmp;
90477 
90478  /* Note: cannot read more than 24 bits without possibly shifting top bits out.
90479  * Fixable, but adds complexity.
90480  */
90481  DUK_ASSERT(bits >= 1 && bits <= 24);
90482 
90483  while (ctx->currbits < bits) {
90484 #if 0
90485  DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
90486  (long) bits, (long) ctx->currbits));
90487 #endif
90488  ctx->currval <<= 8;
90489  if (ctx->offset < ctx->length) {
90490  /* If ctx->offset >= ctx->length, we "shift zeroes in"
90491  * instead of croaking.
90492  */
90493  ctx->currval |= ctx->data[ctx->offset++];
90494  }
90495  ctx->currbits += 8;
90496  }
90497 #if 0
90498  DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
90499  (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
90500 #endif
90501 
90502  /* Extract 'top' bits of currval; note that the extracted bits do not need
90503  * to be cleared, we just ignore them on next round.
90504  */
90505  shift = ctx->currbits - bits;
90506  mask = (1 << bits) - 1;
90507  tmp = (ctx->currval >> shift) & mask;
90508  ctx->currbits = shift; /* remaining */
90509 
90510 #if 0
90511  DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
90512  (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
90513 #endif
90514 
90515  return tmp;
90516 }
90517 
90518 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
90519  return (duk_small_uint_t) duk_bd_decode(ctx, 1);
90520 }
90521 
90522 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
90523  * default value. Return value is signed so that negative marker value can be
90524  * used by caller as a "not present" value.
90525  */
90526 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
90527  if (duk_bd_decode_flag(ctx)) {
90528  return duk_bd_decode(ctx, bits);
90529  } else {
90530  return def_value;
90531  }
90532 }
90533 
90534 /* Shared varint encoding. Match dukutil.py BitEncode.varuint(). */
90535 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
90536  duk_small_uint_t t;
90537 
90538  /* The bit encoding choices here are based on manual testing against
90539  * the actual varuints generated by genbuiltins.py.
90540  */
90541  switch (duk_bd_decode(ctx, 2)) {
90542  case 0:
90543  return 0; /* [0,0] */
90544  case 1:
90545  return duk_bd_decode(ctx, 2) + 1; /* [1,4] */
90546  case 2:
90547  return duk_bd_decode(ctx, 5) + 5; /* [5,36] */
90548  default:
90549  t = duk_bd_decode(ctx, 7);
90550  if (t == 0) {
90551  return duk_bd_decode(ctx, 20);
90552  }
90553  return (t - 1) + 37; /* [37,163] */
90554  }
90555 }
90556 
90557 /* Decode a bit packed string from a custom format used by genbuiltins.py.
90558  * This function is here because it's used for both heap and thread inits.
90559  * Caller must supply the output buffer whose size is NOT checked!
90560  */
90561 
90562 #define DUK__BITPACK_LETTER_LIMIT 26
90563 #define DUK__BITPACK_LOOKUP1 26
90564 #define DUK__BITPACK_LOOKUP2 27
90565 #define DUK__BITPACK_SWITCH1 28
90566 #define DUK__BITPACK_SWITCH 29
90567 #define DUK__BITPACK_UNUSED1 30
90568 #define DUK__BITPACK_EIGHTBIT 31
90569 
90570 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
90571  DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
90572  DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
90573  DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
90574  0xff, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
90575 };
90576 
90577 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
90578  duk_small_uint_t len;
90579  duk_small_uint_t mode;
90580  duk_small_uint_t t;
90581  duk_small_uint_t i;
90582 
90583  len = duk_bd_decode(bd, 5);
90584  if (len == 31) {
90585  len = duk_bd_decode(bd, 8); /* Support up to 256 bytes; rare. */
90586  }
90587 
90588  mode = 32; /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
90589  for (i = 0; i < len; i++) {
90590  t = duk_bd_decode(bd, 5);
90591  if (t < DUK__BITPACK_LETTER_LIMIT) {
90592  t = t + DUK_ASC_UC_A + mode;
90593  } else if (t == DUK__BITPACK_LOOKUP1) {
90594  t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
90595  } else if (t == DUK__BITPACK_LOOKUP2) {
90596  t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
90597  } else if (t == DUK__BITPACK_SWITCH1) {
90598  t = duk_bd_decode(bd, 5);
90599  DUK_ASSERT_DISABLE(t >= 0); /* unsigned */
90600  DUK_ASSERT(t <= 25);
90601  t = t + DUK_ASC_UC_A + (mode ^ 32);
90602  } else if (t == DUK__BITPACK_SWITCH) {
90603  mode = mode ^ 32;
90604  t = duk_bd_decode(bd, 5);
90605  DUK_ASSERT_DISABLE(t >= 0);
90606  DUK_ASSERT(t <= 25);
90607  t = t + DUK_ASC_UC_A + mode;
90608  } else if (t == DUK__BITPACK_EIGHTBIT) {
90609  t = duk_bd_decode(bd, 8);
90610  }
90611  out[i] = (duk_uint8_t) t;
90612  }
90613 
90614  return len;
90615 }
90616 
90617 /* automatic undefs */
90618 #undef DUK__BITPACK_EIGHTBIT
90619 #undef DUK__BITPACK_LETTER_LIMIT
90620 #undef DUK__BITPACK_LOOKUP1
90621 #undef DUK__BITPACK_LOOKUP2
90622 #undef DUK__BITPACK_SWITCH
90623 #undef DUK__BITPACK_SWITCH1
90624 #undef DUK__BITPACK_UNUSED1
90625 /*
90626  * Bitstream encoder.
90627  */
90628 
90629 /* #include duk_internal.h -> already included */
90630 
90631 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
90632  duk_uint8_t tmp;
90633 
90634  DUK_ASSERT(ctx != NULL);
90635  DUK_ASSERT(ctx->currbits < 8);
90636 
90637  /* This limitation would be fixable but adds unnecessary complexity. */
90638  DUK_ASSERT(bits >= 1 && bits <= 24);
90639 
90640  ctx->currval = (ctx->currval << bits) | data;
90641  ctx->currbits += bits;
90642 
90643  while (ctx->currbits >= 8) {
90644  if (ctx->offset < ctx->length) {
90645  tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
90646  ctx->data[ctx->offset++] = tmp;
90647  } else {
90648  /* If buffer has been exhausted, truncate bitstream */
90649  ctx->truncated = 1;
90650  }
90651 
90652  ctx->currbits -= 8;
90653  }
90654 }
90655 
90656 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
90657  duk_small_int_t npad;
90658 
90659  DUK_ASSERT(ctx != NULL);
90660  DUK_ASSERT(ctx->currbits < 8);
90661 
90662  npad = (duk_small_int_t) (8 - ctx->currbits);
90663  if (npad > 0) {
90664  duk_be_encode(ctx, 0, npad);
90665  }
90666  DUK_ASSERT(ctx->currbits == 0);
90667 }
90668 /*
90669  * Fast buffer writer with spare management.
90670  */
90671 
90672 /* #include duk_internal.h -> already included */
90673 
90674 /*
90675  * Macro support functions (use only macros in calling code)
90676  */
90677 
90678 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) {
90679  duk_uint8_t *p;
90680 
90681  DUK_ASSERT(thr != NULL);
90682  DUK_ASSERT(bw_ctx != NULL);
90683  DUK_UNREF(thr);
90684 
90685  p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
90686  DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
90687  bw_ctx->p = p + curr_offset;
90688  bw_ctx->p_base = p;
90689  bw_ctx->p_limit = p + new_length;
90690 }
90691 
90692 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
90693 
90694  DUK_ASSERT(thr != NULL);
90695  DUK_ASSERT(bw_ctx != NULL);
90696  DUK_ASSERT(h_buf != NULL);
90697  DUK_UNREF(thr);
90698 
90699  bw_ctx->buf = h_buf;
90700  duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
90701 }
90702 
90703 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
90704  duk_context *ctx;
90705 
90706  DUK_ASSERT(thr != NULL);
90707  DUK_ASSERT(bw_ctx != NULL);
90708  ctx = (duk_context *) thr;
90709 
90710  (void) duk_push_dynamic_buffer(ctx, buf_size);
90711  bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(ctx, -1);
90712  duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
90713 }
90714 
90715 /* Resize target buffer for requested size. Called by the macro only when the
90716  * fast path test (= there is space) fails.
90717  */
90718 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
90719  duk_size_t curr_off;
90720  duk_size_t add_sz;
90721  duk_size_t new_sz;
90722 
90723  DUK_ASSERT(thr != NULL);
90724  DUK_ASSERT(bw_ctx != NULL);
90725 
90726  /* We could do this operation without caller updating bw_ctx->ptr,
90727  * but by writing it back here we can share code better.
90728  */
90729 
90730  curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
90731  add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
90732  new_sz = curr_off + sz + add_sz;
90733  if (new_sz < curr_off) {
90734  /* overflow */
90735  DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
90736  return NULL; /* not reachable */
90737  }
90738 #if 0 /* for manual torture testing: tight allocation, useful with valgrind */
90739  new_sz = curr_off + sz;
90740 #endif
90741 
90742  /* This is important to ensure dynamic buffer data pointer is not
90743  * NULL (which is possible if buffer size is zero), which in turn
90744  * causes portability issues with e.g. memmove() and memcpy().
90745  */
90746  DUK_ASSERT(new_sz >= 1);
90747 
90748  DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
90749 
90750  duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
90751  duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
90752  return bw_ctx->p;
90753 }
90754 
90755 /* Make buffer compact, matching current written size. */
90756 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
90757  duk_size_t len;
90758 
90759  DUK_ASSERT(thr != NULL);
90760  DUK_ASSERT(bw_ctx != NULL);
90761  DUK_UNREF(thr);
90762 
90763  len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
90764  duk_hbuffer_resize(thr, bw_ctx->buf, len);
90765  duk__bw_update_ptrs(thr, bw_ctx, len, len);
90766 }
90767 
90768 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
90769  duk_uint8_t *p_base;
90770 
90771  DUK_ASSERT(thr != NULL);
90772  DUK_ASSERT(bw != NULL);
90773  DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
90774  DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
90775  DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
90776  DUK_UNREF(thr);
90777 
90778  p_base = bw->p_base;
90779  DUK_MEMCPY((void *) bw->p,
90780  (const void *) (p_base + src_off),
90781  (size_t) len);
90782  bw->p += len;
90783 }
90784 
90785 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
90786  DUK_ASSERT(thr != NULL);
90787  DUK_ASSERT(bw != NULL);
90788  DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
90789  DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
90790  DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
90791  DUK_UNREF(thr);
90792 
90793  DUK_BW_ENSURE(thr, bw, len);
90794  duk_bw_write_raw_slice(thr, bw, src_off, len);
90795 }
90796 
90797 DUK_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) {
90798  duk_uint8_t *p_base;
90799  duk_size_t buf_sz, move_sz;
90800 
90801  DUK_ASSERT(thr != NULL);
90802  DUK_ASSERT(bw != NULL);
90803  DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
90804  DUK_ASSERT(buf != NULL);
90805  DUK_UNREF(thr);
90806 
90807  p_base = bw->p_base;
90808  buf_sz = bw->p - p_base;
90809  move_sz = buf_sz - dst_off;
90810 
90811  DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
90812  DUK_MEMMOVE((void *) (p_base + dst_off + len),
90813  (const void *) (p_base + dst_off),
90814  (size_t) move_sz);
90815  DUK_MEMCPY((void *) (p_base + dst_off),
90816  (const void *) buf,
90817  (size_t) len);
90818  bw->p += len;
90819 }
90820 
90821 DUK_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) {
90822  DUK_ASSERT(thr != NULL);
90823  DUK_ASSERT(bw != NULL);
90824  DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
90825  DUK_ASSERT(buf != NULL);
90826  DUK_UNREF(thr);
90827 
90828  DUK_BW_ENSURE(thr, bw, len);
90829  duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
90830 }
90831 
90832 DUK_INTERNAL 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) {
90833  duk_uint8_t *p_base;
90834  duk_size_t buf_sz, move_sz;
90835 
90836  DUK_ASSERT(thr != NULL);
90837  DUK_ASSERT(bw != NULL);
90838  DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
90839  DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
90840  DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
90841  DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
90842  DUK_UNREF(thr);
90843 
90844  p_base = bw->p_base;
90845 
90846  /* Don't support "straddled" source now. */
90847  DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
90848 
90849  if (dst_off <= src_off) {
90850  /* Target is before source. Source offset is expressed as
90851  * a "before change" offset. Account for the memmove.
90852  */
90853  src_off += len;
90854  }
90855 
90856  buf_sz = bw->p - p_base;
90857  move_sz = buf_sz - dst_off;
90858 
90859  DUK_ASSERT(p_base != NULL); /* buffer size is >= 1 */
90860  DUK_MEMMOVE((void *) (p_base + dst_off + len),
90861  (const void *) (p_base + dst_off),
90862  (size_t) move_sz);
90863  DUK_MEMCPY((void *) (p_base + dst_off),
90864  (const void *) (p_base + src_off),
90865  (size_t) len);
90866  bw->p += len;
90867 }
90868 
90869 DUK_INTERNAL 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) {
90870  DUK_ASSERT(thr != NULL);
90871  DUK_ASSERT(bw != NULL);
90872  DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
90873  DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
90874  DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
90875  DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
90876  DUK_UNREF(thr);
90877 
90878  /* Don't support "straddled" source now. */
90879  DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
90880 
90881  DUK_BW_ENSURE(thr, bw, len);
90882  duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
90883 }
90884 
90885 DUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
90886  duk_uint8_t *p_base, *p_dst, *p_src;
90887  duk_size_t buf_sz, move_sz;
90888 
90889  DUK_ASSERT(thr != NULL);
90890  DUK_ASSERT(bw != NULL);
90891  DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
90892  DUK_UNREF(thr);
90893 
90894  p_base = bw->p_base;
90895  buf_sz = bw->p - p_base;
90896  move_sz = buf_sz - off;
90897  p_dst = p_base + off + len;
90898  p_src = p_base + off;
90899  DUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);
90900  return p_src; /* point to start of 'reserved area' */
90901 }
90902 
90903 DUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
90904  DUK_ASSERT(thr != NULL);
90905  DUK_ASSERT(bw != NULL);
90906  DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
90907  DUK_UNREF(thr);
90908 
90909  DUK_BW_ENSURE(thr, bw, len);
90910  return duk_bw_insert_raw_area(thr, bw, off, len);
90911 }
90912 
90913 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
90914  duk_size_t move_sz;
90915 
90916  duk_uint8_t *p_base;
90917  duk_uint8_t *p_src;
90918  duk_uint8_t *p_dst;
90919 
90920  DUK_ASSERT(thr != NULL);
90921  DUK_ASSERT(bw != NULL);
90922  DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
90923  DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
90924  DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
90925  DUK_UNREF(thr);
90926 
90927  p_base = bw->p_base;
90928  p_dst = p_base + off;
90929  p_src = p_dst + len;
90930  move_sz = (duk_size_t) (bw->p - p_src);
90931  DUK_MEMMOVE((void *) p_dst,
90932  (const void *) p_src,
90933  (size_t) move_sz);
90934  bw->p -= len;
90935 }
90936 
90937 /*
90938  * Macro support functions for reading/writing raw data.
90939  *
90940  * These are done using mempcy to ensure they're valid even for unaligned
90941  * reads/writes on platforms where alignment counts. On x86 at least gcc
90942  * is able to compile these into a bswap+mov. "Always inline" is used to
90943  * ensure these macros compile to minimal code.
90944  *
90945  * Not really bufwriter related, but currently used together.
90946  */
90947 
90948 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
90949  union {
90950  duk_uint8_t b[2];
90951  duk_uint16_t x;
90952  } u;
90953 
90954  DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);
90955  u.x = DUK_NTOH16(u.x);
90956  *p += 2;
90957  return u.x;
90958 }
90959 
90960 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
90961  union {
90962  duk_uint8_t b[4];
90963  duk_uint32_t x;
90964  } u;
90965 
90966  DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
90967  u.x = DUK_NTOH32(u.x);
90968  *p += 4;
90969  return u.x;
90970 }
90971 
90972 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
90973  duk_double_union du;
90974  union {
90975  duk_uint8_t b[4];
90976  duk_uint32_t x;
90977  } u;
90978 
90979  DUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);
90980  u.x = DUK_NTOH32(u.x);
90981  du.ui[DUK_DBL_IDX_UI0] = u.x;
90982  DUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);
90983  u.x = DUK_NTOH32(u.x);
90984  du.ui[DUK_DBL_IDX_UI1] = u.x;
90985  *p += 8;
90986 
90987  return du.d;
90988 }
90989 
90990 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
90991  union {
90992  duk_uint8_t b[2];
90993  duk_uint16_t x;
90994  } u;
90995 
90996  u.x = DUK_HTON16(val);
90997  DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);
90998  *p += 2;
90999 }
91000 
91001 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
91002  union {
91003  duk_uint8_t b[4];
91004  duk_uint32_t x;
91005  } u;
91006 
91007  u.x = DUK_HTON32(val);
91008  DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
91009  *p += 4;
91010 }
91011 
91012 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
91013  duk_double_union du;
91014  union {
91015  duk_uint8_t b[4];
91016  duk_uint32_t x;
91017  } u;
91018 
91019  du.d = val;
91020  u.x = du.ui[DUK_DBL_IDX_UI0];
91021  u.x = DUK_HTON32(u.x);
91022  DUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);
91023  u.x = du.ui[DUK_DBL_IDX_UI1];
91024  u.x = DUK_HTON32(u.x);
91025  DUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);
91026  *p += 8;
91027 }
91028 /*
91029  * Hash function duk_util_hashbytes().
91030  *
91031  * Currently, 32-bit MurmurHash2.
91032  *
91033  * Don't rely on specific hash values; hash function may be endianness
91034  * dependent, for instance.
91035  */
91036 
91037 /* #include duk_internal.h -> already included */
91038 
91039 #if defined(DUK_USE_STRHASH_DENSE)
91040 /* 'magic' constants for Murmurhash2 */
91041 #define DUK__MAGIC_M ((duk_uint32_t) 0x5bd1e995UL)
91042 #define DUK__MAGIC_R 24
91043 
91044 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
91045  duk_uint32_t h = seed ^ ((duk_uint32_t) len);
91046 
91047  while (len >= 4) {
91048  /* Portability workaround is required for platforms without
91049  * unaligned access. The replacement code emulates little
91050  * endian access even on big endian architectures, which is
91051  * OK as long as it is consistent for a build.
91052  */
91053 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
91054  duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
91055 #else
91056  duk_uint32_t k = ((duk_uint32_t) data[0]) |
91057  (((duk_uint32_t) data[1]) << 8) |
91058  (((duk_uint32_t) data[2]) << 16) |
91059  (((duk_uint32_t) data[3]) << 24);
91060 #endif
91061 
91062  k *= DUK__MAGIC_M;
91063  k ^= k >> DUK__MAGIC_R;
91064  k *= DUK__MAGIC_M;
91065  h *= DUK__MAGIC_M;
91066  h ^= k;
91067  data += 4;
91068  len -= 4;
91069  }
91070 
91071  switch (len) {
91072  case 3: h ^= data[2] << 16;
91073  case 2: h ^= data[1] << 8;
91074  case 1: h ^= data[0];
91075  h *= DUK__MAGIC_M;
91076  }
91077 
91078  h ^= h >> 13;
91079  h *= DUK__MAGIC_M;
91080  h ^= h >> 15;
91081 
91082  return h;
91083 }
91084 #endif /* DUK_USE_STRHASH_DENSE */
91085 
91086 /* automatic undefs */
91087 #undef DUK__MAGIC_M
91088 #undef DUK__MAGIC_R
91089 /*
91090  * A tiny random number generator used for Math.random() and other internals.
91091  *
91092  * Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
91093  * with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
91094  *
91095  * Low memory targets and targets without 64-bit types use a slightly smaller
91096  * (but slower) algorithm by Adi Shamir:
91097  * http://www.woodmann.com/forum/archive/index.php/t-3100.html.
91098  *
91099  */
91100 
91101 /* #include duk_internal.h -> already included */
91102 
91103 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
91104 
91105 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
91106 #define DUK__RANDOM_SHAMIR3OP
91107 #else
91108 #define DUK__RANDOM_XOROSHIRO128PLUS
91109 #endif
91110 
91111 #if defined(DUK__RANDOM_SHAMIR3OP)
91112 #define DUK__UPDATE_RND(rnd) do { \
91113  (rnd) += ((rnd) * (rnd)) | 0x05UL; \
91114  (rnd) = ((rnd) & 0xffffffffUL); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
91115  } while (0)
91116 
91117 #define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */
91118 
91119 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
91120  DUK_UNREF(thr); /* Nothing now. */
91121 }
91122 
91123 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
91124  duk_double_t t;
91125  duk_small_int_t n;
91126  duk_uint32_t rnd;
91127 
91128  rnd = thr->heap->rnd_state;
91129 
91130  n = 53; /* enough to cover the whole mantissa */
91131  t = 0.0;
91132 
91133  do {
91134  DUK__UPDATE_RND(rnd);
91135  t += DUK__RND_BIT(rnd);
91136  t /= 2.0;
91137  } while (--n);
91138 
91139  thr->heap->rnd_state = rnd;
91140 
91141  DUK_ASSERT(t >= (duk_double_t) 0.0);
91142  DUK_ASSERT(t < (duk_double_t) 1.0);
91143 
91144  return t;
91145 }
91146 #endif /* DUK__RANDOM_SHAMIR3OP */
91147 
91148 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
91149 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
91150  duk_uint64_t z;
91151  z = (*x += 0x9E3779B97F4A7C15ULL);
91152  z = (z ^ (z >> 30U)) * 0xBF58476D1CE4E5B9ULL;
91153  z = (z ^ (z >> 27U)) * 0x94D049BB133111EBULL;
91154  return z ^ (z >> 31U);
91155 }
91156 
91157 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
91158  return (x << k) | (x >> (64U - k));
91159 }
91160 
91161 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
91162  duk_uint64_t s0;
91163  duk_uint64_t s1;
91164  duk_uint64_t res;
91165 
91166  s0 = s[0];
91167  s1 = s[1];
91168  res = s0 + s1;
91169  s1 ^= s0;
91170  s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
91171  s[1] = duk__rnd_rotl(s1, 36);
91172 
91173  return res;
91174 }
91175 
91176 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
91177  duk_small_uint_t i;
91178  duk_uint64_t x;
91179 
91180  /* Mix both halves of the initial seed with SplitMix64. The intent
91181  * is to ensure that very similar raw seeds (which is usually the case
91182  * because current seed is Date.now()) result in different xoroshiro128+
91183  * seeds.
91184  */
91185  x = thr->heap->rnd_state[0]; /* Only [0] is used as input here. */
91186  for (i = 0; i < 64; i++) {
91187  thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x); /* Keep last 2 values. */
91188  }
91189 }
91190 
91191 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
91192  duk_uint64_t v;
91193  duk_double_union du;
91194 
91195  /* For big and little endian the integer and IEEE double byte order
91196  * is the same so a direct assignment works. For mixed endian the
91197  * 32-bit parts must be swapped.
91198  */
91199  v = (0x3ffULL << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
91200  du.ull[0] = v;
91201 #if defined(DUK_USE_DOUBLE_ME)
91202  do {
91203  duk_uint32_t tmp;
91204  tmp = du.ui[0];
91205  du.ui[0] = du.ui[1];
91206  du.ui[1] = tmp;
91207  } while (0);
91208 #endif
91209  return du.d - 1.0;
91210 }
91211 #endif /* DUK__RANDOM_XOROSHIRO128PLUS */
91212 
91213 #endif /* !DUK_USE_GET_RANDOM_DOUBLE */
91214 
91215 /* automatic undefs */
91216 #undef DUK__RANDOM_SHAMIR3OP
91217 #undef DUK__RANDOM_XOROSHIRO128PLUS
91218 #undef DUK__RND_BIT
91219 #undef DUK__UPDATE_RND
Definition: duktape.h:230
Definition: duktape.h:224
Definition: duktape.c:7743
Definition: Viewer.h:174