2 * Initialize built-in objects. Current thread must have a valstack
3 * and initialization errors may longjmp, so a setjmp() catch point
7 #include "duk_internal.h"
10 * Encoding constants, must match genbuiltins.py
13 #define DUK__CLASS_BITS 5
14 #define DUK__BIDX_BITS 7
15 #define DUK__STRIDX_BITS 9 /* XXX: try to optimize to 8 (would now be possible, <200 used) */
16 #define DUK__NATIDX_BITS 8
17 #define DUK__NUM_NORMAL_PROPS_BITS 6
18 #define DUK__NUM_FUNC_PROPS_BITS 6
19 #define DUK__PROP_FLAGS_BITS 3
20 #define DUK__STRING_LENGTH_BITS 8
21 #define DUK__STRING_CHAR_BITS 7
22 #define DUK__LENGTH_PROP_BITS 3
23 #define DUK__NARGS_BITS 3
24 #define DUK__PROP_TYPE_BITS 3
25 #define DUK__MAGIC_BITS 16
27 #define DUK__NARGS_VARARGS_MARKER 0x07
28 #define DUK__NO_CLASS_MARKER 0x00 /* 0 = DUK_HOBJECT_CLASS_UNUSED */
29 #define DUK__NO_BIDX_MARKER 0x7f
30 #define DUK__NO_STRIDX_MARKER 0xff
32 #define DUK__PROP_TYPE_DOUBLE 0
33 #define DUK__PROP_TYPE_STRING 1
34 #define DUK__PROP_TYPE_STRIDX 2
35 #define DUK__PROP_TYPE_BUILTIN 3
36 #define DUK__PROP_TYPE_UNDEFINED 4
37 #define DUK__PROP_TYPE_BOOLEAN_TRUE 5
38 #define DUK__PROP_TYPE_BOOLEAN_FALSE 6
39 #define DUK__PROP_TYPE_ACCESSOR 7
42 * Create built-in objects by parsing an init bitstream generated
46 #if defined(DUK_USE_ROM_OBJECTS)
47 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
48 DUK_LOCAL
void duk__duplicate_ram_global_object(duk_hthread
*thr
) {
51 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
54 duk_size_t alloc_size
;
57 ctx
= (duk_context
*) thr
;
59 /* XXX: refactor into internal helper, duk_clone_hobject() */
61 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
62 /* Inherit from ROM-based global object: less RAM usage, less transparent. */
63 duk_push_object_helper(ctx
,
64 DUK_HOBJECT_FLAG_EXTENSIBLE
|
65 DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL
),
67 h1
= duk_get_hobject(ctx
, -1);
68 DUK_ASSERT(h1
!= NULL
);
69 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
70 /* Clone the properties of the ROM-based global object to create a
71 * fully RAM-based global object. Uses more memory than the inherit
72 * model but more compliant.
74 duk_push_object_helper(ctx
,
75 DUK_HOBJECT_FLAG_EXTENSIBLE
|
76 DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL
),
77 DUK_BIDX_OBJECT_PROTOTYPE
);
78 h1
= duk_get_hobject(ctx
, -1);
79 DUK_ASSERT(h1
!= NULL
);
80 h2
= thr
->builtins
[DUK_BIDX_GLOBAL
];
81 DUK_ASSERT(h2
!= NULL
);
83 /* Copy the property table verbatim; this handles attributes etc.
84 * For ROM objects it's not necessary (or possible) to update
85 * refcounts so leave them as is.
87 alloc_size
= DUK_HOBJECT_P_ALLOC_SIZE(h2
);
88 DUK_ASSERT(alloc_size
> 0);
89 props
= DUK_ALLOC(thr
->heap
, alloc_size
);
91 DUK_ERROR_ALLOC_DEFMSG(thr
);
94 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr
->heap
, h2
) != NULL
);
95 DUK_MEMCPY((void *) props
, (const void *) DUK_HOBJECT_GET_PROPS(thr
->heap
, h2
), alloc_size
);
97 /* XXX: keep property attributes or tweak them here?
98 * Properties will now be non-configurable even when they're
99 * normally configurable for the global object.
102 DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr
->heap
, h1
) == NULL
);
103 DUK_HOBJECT_SET_PROPS(thr
->heap
, h1
, props
);
104 DUK_HOBJECT_SET_ESIZE(h1
, DUK_HOBJECT_GET_ESIZE(h2
));
105 DUK_HOBJECT_SET_ENEXT(h1
, DUK_HOBJECT_GET_ENEXT(h2
));
106 DUK_HOBJECT_SET_ASIZE(h1
, DUK_HOBJECT_GET_ASIZE(h2
));
107 DUK_HOBJECT_SET_HSIZE(h1
, DUK_HOBJECT_GET_HSIZE(h2
));
109 #error internal error in defines
112 duk_hobject_compact_props(thr
, h1
);
113 DUK_ASSERT(thr
->builtins
[DUK_BIDX_GLOBAL
] != NULL
);
114 DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr
*) thr
->builtins
[DUK_BIDX_GLOBAL
])); /* no need to decref */
115 thr
->builtins
[DUK_BIDX_GLOBAL
] = h1
;
116 DUK_HOBJECT_INCREF(thr
, h1
);
117 DUK_D(DUK_DPRINT("duplicated global object: %!O", h1
));
120 /* Create a fresh object environment for the global scope. This is
121 * needed so that the global scope points to the newly created RAM-based
124 duk_push_object_helper(ctx
,
125 DUK_HOBJECT_FLAG_EXTENSIBLE
|
126 DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV
),
127 -1); /* no prototype */
128 h1
= duk_get_hobject(ctx
, -1);
129 DUK_ASSERT(h1
!= NULL
);
131 duk_dup(ctx
, -1); /* -> [ ... new_global new_globalenv new_global new_global ] */
132 duk_xdef_prop_stridx(thr
, -3, DUK_STRIDX_INT_TARGET
, DUK_PROPDESC_FLAGS_NONE
);
133 duk_xdef_prop_stridx(thr
, -2, DUK_STRIDX_INT_THIS
, DUK_PROPDESC_FLAGS_NONE
); /* always provideThis=true */
135 duk_hobject_compact_props(thr
, h1
);
136 DUK_ASSERT(thr
->builtins
[DUK_BIDX_GLOBAL_ENV
] != NULL
);
137 DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr
*) thr
->builtins
[DUK_BIDX_GLOBAL_ENV
])); /* no need to decref */
138 thr
->builtins
[DUK_BIDX_GLOBAL_ENV
] = h1
;
139 DUK_HOBJECT_INCREF(thr
, h1
);
140 DUK_D(DUK_DPRINT("duplicated global env: %!O", h1
));
144 #endif /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
146 DUK_INTERNAL
void duk_hthread_create_builtin_objects(duk_hthread
*thr
) {
147 /* Setup builtins from ROM objects. All heaps/threads will share
148 * the same readonly objects.
152 for (i
= 0; i
< DUK_NUM_BUILTINS
; i
++) {
154 h
= (duk_hobject
*) DUK_LOSE_CONST(duk_rom_builtins_bidx
[i
]);
155 DUK_ASSERT(h
!= NULL
);
156 thr
->builtins
[i
] = h
;
159 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
160 /* By default the global object is read-only which is often much
161 * more of an issue than having read-only built-in objects (like
162 * RegExp, Date, etc). Use a RAM-based copy of the global object
163 * and the global environment object for convenience.
165 duk__duplicate_ram_global_object(thr
);
168 #else /* DUK_USE_ROM_OBJECTS */
169 DUK_LOCAL
void duk__push_stridx(duk_context
*ctx
, duk_bitdecoder_ctx
*bd
) {
172 n
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__STRIDX_BITS
);
173 DUK_ASSERT_DISABLE(n
>= 0); /* unsigned */
174 DUK_ASSERT(n
< DUK_HEAP_NUM_STRINGS
);
175 duk_push_hstring_stridx(ctx
, n
);
177 DUK_LOCAL
void duk__push_string(duk_context
*ctx
, duk_bitdecoder_ctx
*bd
) {
182 n
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__STRING_LENGTH_BITS
);
183 p
= (duk_uint8_t
*) duk_push_fixed_buffer(ctx
, n
);
184 for (i
= 0; i
< n
; i
++) {
185 *p
++ = (duk_uint8_t
) duk_bd_decode(bd
, DUK__STRING_CHAR_BITS
);
187 duk_to_string(ctx
, -1);
189 DUK_LOCAL
void duk__push_stridx_or_string(duk_context
*ctx
, duk_bitdecoder_ctx
*bd
) {
190 if (duk_bd_decode_flag(bd
)) {
191 duk__push_string(ctx
, bd
);
193 duk__push_stridx(ctx
, bd
);
196 DUK_LOCAL
void duk__push_double(duk_context
*ctx
, duk_bitdecoder_ctx
*bd
) {
200 for (i
= 0; i
< 8; i
++) {
201 /* Encoding endianness must match target memory layout,
202 * build scripts and genbuiltins.py must ensure this.
204 du
.uc
[i
] = (duk_uint8_t
) duk_bd_decode(bd
, 8);
207 duk_push_number(ctx
, du
.d
); /* push operation normalizes NaNs */
210 DUK_INTERNAL
void duk_hthread_create_builtin_objects(duk_hthread
*thr
) {
211 duk_context
*ctx
= (duk_context
*) thr
;
212 duk_bitdecoder_ctx bd_ctx
;
213 duk_bitdecoder_ctx
*bd
= &bd_ctx
; /* convenience */
215 duk_small_uint_t i
, j
;
217 DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS
, (int) DUK_NUM_ALL_BUILTINS
));
219 DUK_MEMZERO(&bd_ctx
, sizeof(bd_ctx
));
220 bd
->data
= (const duk_uint8_t
*) duk_builtins_data
;
221 bd
->length
= (duk_size_t
) DUK_BUILTINS_DATA_LENGTH
;
224 * First create all built-in bare objects on the empty valstack.
226 * Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
227 * stack indices matching their eventual thr->builtins[] index.
229 * Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
230 * will exist on the value stack during init but won't be placed
231 * into thr->builtins[]. These are objects referenced in some way
232 * from thr->builtins[] roots but which don't need to be indexed by
233 * Duktape through thr->builtins[] (e.g. user custom objects).
236 duk_require_stack(ctx
, DUK_NUM_ALL_BUILTINS
);
238 DUK_DD(DUK_DDPRINT("create empty built-ins"));
239 DUK_ASSERT_TOP(ctx
, 0);
240 for (i
= 0; i
< DUK_NUM_ALL_BUILTINS
; i
++) {
241 duk_small_uint_t class_num
;
242 duk_small_int_t len
= -1; /* must be signed */
244 class_num
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__CLASS_BITS
);
245 len
= (duk_small_int_t
) duk_bd_decode_flagged(bd
, DUK__LENGTH_PROP_BITS
, (duk_int32_t
) -1 /*def_value*/);
247 if (class_num
== DUK_HOBJECT_CLASS_FUNCTION
) {
248 duk_small_uint_t natidx
;
249 duk_int_t c_nargs
; /* must hold DUK_VARARGS */
250 duk_c_function c_func
;
253 DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len
));
254 DUK_ASSERT(len
>= 0);
256 natidx
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NATIDX_BITS
);
257 c_func
= duk_bi_native_functions
[natidx
];
259 c_nargs
= (duk_small_uint_t
) duk_bd_decode_flagged(bd
, DUK__NARGS_BITS
, len
/*def_value*/);
260 if (c_nargs
== DUK__NARGS_VARARGS_MARKER
) {
261 c_nargs
= DUK_VARARGS
;
264 /* XXX: set magic directly here? (it could share the c_nargs arg) */
265 duk_push_c_function_noexotic(ctx
, c_func
, c_nargs
);
267 h
= duk_require_hobject(ctx
, -1);
268 DUK_ASSERT(h
!= NULL
);
270 /* Currently all built-in native functions are strict.
271 * duk_push_c_function() now sets strict flag, so
274 DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h
));
276 /* XXX: function properties */
278 /* Built-in 'name' is not writable by default. Function '.name'
279 * is writable to allow user code to set a '.name' on a native
282 duk__push_stridx_or_string(ctx
, bd
);
283 duk_xdef_prop_stridx(ctx
,
286 (i
== DUK_BIDX_FUNCTION_PROTOTYPE
) ?
287 DUK_PROPDESC_FLAGS_W
: DUK_PROPDESC_FLAGS_NONE
);
289 /* Almost all global level Function objects are constructable
290 * but not all: Function.prototype is a non-constructable,
293 if (duk_bd_decode_flag(bd
)) {
294 DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h
));
296 DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h
);
299 /* Cast converts magic to 16-bit signed value */
300 magic
= (duk_int16_t
) duk_bd_decode_flagged(bd
, DUK__MAGIC_BITS
, 0 /*def_value*/);
301 ((duk_hnativefunction
*) h
)->magic
= magic
;
303 /* XXX: ARRAY_PART for Array prototype? */
305 duk_push_object_helper(ctx
,
306 DUK_HOBJECT_FLAG_EXTENSIBLE
,
307 -1); /* no prototype or class yet */
309 h
= duk_require_hobject(ctx
, -1);
310 DUK_ASSERT(h
!= NULL
);
313 DUK_HOBJECT_SET_CLASS_NUMBER(h
, class_num
);
315 if (i
< DUK_NUM_BUILTINS
) {
316 thr
->builtins
[i
] = h
;
317 DUK_HOBJECT_INCREF(thr
, &h
->hdr
);
322 * For top-level objects, 'length' property has the following
323 * default attributes: non-writable, non-enumerable, non-configurable
326 * However, 'length' property for Array.prototype has attributes
327 * expected of an Array instance which are different: writable,
328 * non-enumerable, non-configurable (E5 Section 15.4.5.2).
330 * This is currently determined implicitly based on class; there are
331 * no attribute flags in the init data.
334 duk_push_int(ctx
, len
);
335 duk_xdef_prop_stridx(ctx
,
338 (class_num
== DUK_HOBJECT_CLASS_ARRAY
? /* only Array.prototype matches */
339 DUK_PROPDESC_FLAGS_W
: DUK_PROPDESC_FLAGS_NONE
));
342 /* enable exotic behaviors last */
344 if (class_num
== DUK_HOBJECT_CLASS_ARRAY
) {
345 DUK_HOBJECT_SET_EXOTIC_ARRAY(h
);
347 if (class_num
== DUK_HOBJECT_CLASS_STRING
) {
348 DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h
);
351 /* some assertions */
353 DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h
));
354 /* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
355 DUK_ASSERT(!DUK_HOBJECT_HAS_BOUND(h
));
356 DUK_ASSERT(!DUK_HOBJECT_HAS_COMPILEDFUNCTION(h
));
357 /* DUK_HOBJECT_FLAG_NATIVEFUNCTION varies */
358 DUK_ASSERT(!DUK_HOBJECT_HAS_THREAD(h
));
359 DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h
)); /* currently, even for Array.prototype */
360 /* DUK_HOBJECT_FLAG_STRICT varies */
361 DUK_ASSERT(!DUK_HOBJECT_HAS_NATIVEFUNCTION(h
) || /* all native functions have NEWENV */
362 DUK_HOBJECT_HAS_NEWENV(h
));
363 DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h
));
364 DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h
));
365 DUK_ASSERT(!DUK_HOBJECT_HAS_ENVRECCLOSED(h
));
366 /* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
367 /* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
368 DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h
));
370 DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i
, (long) class_num
, (long) len
));
374 * Then decode the builtins init data (see genbuiltins.py) to
378 DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
379 for (i
= 0; i
< DUK_NUM_ALL_BUILTINS
; i
++) {
381 duk_small_uint_t num
;
383 DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i
));
384 h
= duk_require_hobject(ctx
, i
);
385 DUK_ASSERT(h
!= NULL
);
387 t
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__BIDX_BITS
);
388 if (t
!= DUK__NO_BIDX_MARKER
) {
389 DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t
));
390 DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr
, h
, duk_require_hobject(ctx
, t
));
393 t
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__BIDX_BITS
);
394 if (t
!= DUK__NO_BIDX_MARKER
) {
395 /* 'prototype' property for all built-in objects (which have it) has attributes:
396 * [[Writable]] = false,
397 * [[Enumerable]] = false,
398 * [[Configurable]] = false
400 DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t
));
401 duk_xdef_prop_stridx_builtin(ctx
, i
, DUK_STRIDX_PROTOTYPE
, t
, DUK_PROPDESC_FLAGS_NONE
);
404 t
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__BIDX_BITS
);
405 if (t
!= DUK__NO_BIDX_MARKER
) {
406 /* 'constructor' property for all built-in objects (which have it) has attributes:
407 * [[Writable]] = true,
408 * [[Enumerable]] = false,
409 * [[Configurable]] = true
411 DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t
));
412 duk_xdef_prop_stridx_builtin(ctx
, i
, DUK_STRIDX_CONSTRUCTOR
, t
, DUK_PROPDESC_FLAGS_WC
);
415 /* normal valued properties */
416 num
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NUM_NORMAL_PROPS_BITS
);
417 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i
, (long) num
));
418 for (j
= 0; j
< num
; j
++) {
419 duk_small_uint_t prop_flags
;
421 duk__push_stridx_or_string(ctx
, bd
);
424 * Property attribute defaults are defined in E5 Section 15 (first
425 * few pages); there is a default for all properties and a special
426 * default for 'length' properties. Variation from the defaults is
427 * signaled using a single flag bit in the bitstream.
430 if (duk_bd_decode_flag(bd
)) {
431 prop_flags
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__PROP_FLAGS_BITS
);
433 prop_flags
= DUK_PROPDESC_FLAGS_WC
;
436 t
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__PROP_TYPE_BITS
);
438 DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
439 (long) i
, (long) j
, duk_get_tval(ctx
, -1), (unsigned long) prop_flags
, (long) t
));
442 case DUK__PROP_TYPE_DOUBLE
: {
443 duk__push_double(ctx
, bd
);
446 case DUK__PROP_TYPE_STRING
: {
447 duk__push_string(ctx
, bd
);
450 case DUK__PROP_TYPE_STRIDX
: {
451 duk__push_stridx(ctx
, bd
);
454 case DUK__PROP_TYPE_BUILTIN
: {
455 duk_small_uint_t bidx
;
457 bidx
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__BIDX_BITS
);
458 DUK_ASSERT(bidx
!= DUK__NO_BIDX_MARKER
);
459 duk_dup(ctx
, (duk_idx_t
) bidx
);
462 case DUK__PROP_TYPE_UNDEFINED
: {
463 duk_push_undefined(ctx
);
466 case DUK__PROP_TYPE_BOOLEAN_TRUE
: {
470 case DUK__PROP_TYPE_BOOLEAN_FALSE
: {
474 case DUK__PROP_TYPE_ACCESSOR
: {
475 duk_small_uint_t natidx_getter
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NATIDX_BITS
);
476 duk_small_uint_t natidx_setter
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NATIDX_BITS
);
477 duk_c_function c_func_getter
;
478 duk_c_function c_func_setter
;
480 /* XXX: this is a bit awkward because there is no exposed helper
481 * in the API style, only this internal helper.
483 DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
484 (long) i
, duk_get_tval(ctx
, -1), (long) natidx_getter
, (long) natidx_setter
, (unsigned long) prop_flags
));
486 c_func_getter
= duk_bi_native_functions
[natidx_getter
];
487 c_func_setter
= duk_bi_native_functions
[natidx_setter
];
488 duk_push_c_function_noconstruct_noexotic(ctx
, c_func_getter
, 0); /* always 0 args */
489 duk_push_c_function_noconstruct_noexotic(ctx
, c_func_setter
, 1); /* always 1 arg */
491 /* XXX: magic for getter/setter? use duk_def_prop()? */
493 DUK_ASSERT((prop_flags
& DUK_PROPDESC_FLAG_WRITABLE
) == 0); /* genbuiltins.py ensures */
495 prop_flags
|= DUK_PROPDESC_FLAG_ACCESSOR
; /* accessor flag not encoded explicitly */
496 duk_hobject_define_accessor_internal(thr
,
497 duk_require_hobject(ctx
, i
),
498 duk_get_hstring(ctx
, -3),
499 duk_require_hobject(ctx
, -2),
500 duk_require_hobject(ctx
, -1),
502 duk_pop_3(ctx
); /* key, getter and setter, now reachable through object */
511 DUK_ASSERT((prop_flags
& DUK_PROPDESC_FLAG_ACCESSOR
) == 0);
512 duk_xdef_prop(ctx
, i
, prop_flags
);
515 continue; /* avoid empty label at the end of a compound statement */
518 /* native function properties */
519 num
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NUM_FUNC_PROPS_BITS
);
520 DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i
, (long) num
));
521 for (j
= 0; j
< num
; j
++) {
523 duk_small_uint_t natidx
;
524 duk_int_t c_nargs
; /* must hold DUK_VARARGS */
525 duk_small_uint_t c_length
;
527 duk_c_function c_func
;
528 duk_hnativefunction
*h_func
;
529 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
530 duk_small_int_t lightfunc_eligible
;
533 duk__push_stridx_or_string(ctx
, bd
);
534 h_key
= duk_get_hstring(ctx
, -1);
535 DUK_ASSERT(h_key
!= NULL
);
537 natidx
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__NATIDX_BITS
);
539 c_length
= (duk_small_uint_t
) duk_bd_decode(bd
, DUK__LENGTH_PROP_BITS
);
540 c_nargs
= (duk_int_t
) duk_bd_decode_flagged(bd
, DUK__NARGS_BITS
, (duk_int32_t
) c_length
/*def_value*/);
541 if (c_nargs
== DUK__NARGS_VARARGS_MARKER
) {
542 c_nargs
= DUK_VARARGS
;
545 c_func
= duk_bi_native_functions
[natidx
];
547 DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
548 (long) i
, (long) j
, (duk_heaphdr
*) h_key
, (long) natidx
, (long) c_length
,
549 (c_nargs
== DUK_VARARGS
? (long) -1 : (long) c_nargs
)));
551 /* Cast converts magic to 16-bit signed value */
552 magic
= (duk_int16_t
) duk_bd_decode_flagged(bd
, DUK__MAGIC_BITS
, 0);
554 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
556 ((c_nargs
>= DUK_LFUNC_NARGS_MIN
&& c_nargs
<= DUK_LFUNC_NARGS_MAX
) || (c_nargs
== DUK_VARARGS
)) &&
557 (c_length
<= DUK_LFUNC_LENGTH_MAX
) &&
558 (magic
>= DUK_LFUNC_MAGIC_MIN
&& magic
<= DUK_LFUNC_MAGIC_MAX
);
560 if (h_key
== DUK_HTHREAD_STRING_EVAL(thr
) ||
561 h_key
== DUK_HTHREAD_STRING_YIELD(thr
) ||
562 h_key
== DUK_HTHREAD_STRING_RESUME(thr
) ||
563 h_key
== DUK_HTHREAD_STRING_REQUIRE(thr
)) {
564 /* These functions have trouble working as lightfuncs.
565 * Some of them have specific asserts and some may have
566 * additional properties (e.g. 'require.id' may be written).
568 DUK_D(DUK_DPRINT("reject as lightfunc: key=%!O, i=%d, j=%d", (duk_heaphdr
*) h_key
, (int) i
, (int) j
));
569 lightfunc_eligible
= 0;
572 if (lightfunc_eligible
) {
574 duk_small_uint_t lf_nargs
= (c_nargs
== DUK_VARARGS
? DUK_LFUNC_NARGS_VARARGS
: c_nargs
);
575 duk_small_uint_t lf_flags
= DUK_LFUNC_FLAGS_PACK(magic
, c_length
, lf_nargs
);
576 DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc
, c_func
, lf_flags
);
577 duk_push_tval(ctx
, &tv_lfunc
);
578 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)));
582 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
));
583 #endif /* DUK_USE_LIGHTFUNC_BUILTINS */
585 /* [ (builtin objects) name ] */
587 duk_push_c_function_noconstruct_noexotic(ctx
, c_func
, c_nargs
);
588 h_func
= duk_require_hnativefunction(ctx
, -1);
591 /* Currently all built-in native functions are strict.
592 * This doesn't matter for many functions, but e.g.
593 * String.prototype.charAt (and other string functions)
594 * rely on being strict so that their 'this' binding is
595 * not automatically coerced.
597 DUK_HOBJECT_SET_STRICT((duk_hobject
*) h_func
);
599 /* No built-in functions are constructable except the top
600 * level ones (Number, etc).
602 DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject
*) h_func
));
604 /* XXX: any way to avoid decoding magic bit; there are quite
605 * many function properties and relatively few with magic values.
607 h_func
->magic
= magic
;
609 /* [ (builtin objects) name func ] */
611 duk_push_int(ctx
, c_length
);
612 duk_xdef_prop_stridx(ctx
, -2, DUK_STRIDX_LENGTH
, DUK_PROPDESC_FLAGS_NONE
);
615 duk_xdef_prop_stridx(ctx
, -2, DUK_STRIDX_NAME
, DUK_PROPDESC_FLAGS_NONE
);
617 /* XXX: other properties of function instances; 'arguments', 'caller'. */
619 DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
620 (long) i
, (long) j
, (duk_tval
*) duk_get_tval(ctx
, -1)));
622 /* [ (builtin objects) name func ] */
625 * The default property attributes are correct for all
626 * function valued properties of built-in objects now.
629 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
633 duk_xdef_prop(ctx
, i
, DUK_PROPDESC_FLAGS_WC
);
635 /* [ (builtin objects) ] */
640 * Special post-tweaks, for cases not covered by the init data format.
642 * - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
643 * toGMTString is required to have the same Function object as
644 * toUTCString in E5 Section B.2.6. Note that while Smjs respects
645 * this, V8 does not (the Function objects are distinct).
647 * - Make DoubleError non-extensible.
649 * - Add info about most important effective compile options to Duktape.
651 * - Possibly remove some properties (values or methods) which are not
652 * desirable with current feature options but are not currently
653 * conditional in init data.
656 duk_get_prop_stridx(ctx
, DUK_BIDX_DATE_PROTOTYPE
, DUK_STRIDX_TO_UTC_STRING
);
657 duk_xdef_prop_stridx(ctx
, DUK_BIDX_DATE_PROTOTYPE
, DUK_STRIDX_TO_GMT_STRING
, DUK_PROPDESC_FLAGS_WC
);
659 h
= duk_require_hobject(ctx
, DUK_BIDX_DOUBLE_ERROR
);
660 DUK_ASSERT(h
!= NULL
);
661 DUK_HOBJECT_CLEAR_EXTENSIBLE(h
);
663 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
664 DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
665 (void) duk_hobject_delprop_raw(thr
, thr
->builtins
[DUK_BIDX_OBJECT_PROTOTYPE
], DUK_HTHREAD_STRING___PROTO__(thr
), DUK_DELPROP_FLAG_THROW
);
668 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
669 DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
670 (void) duk_hobject_delprop_raw(thr
, thr
->builtins
[DUK_BIDX_OBJECT_CONSTRUCTOR
], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr
), DUK_DELPROP_FLAG_THROW
);
675 /* Endianness indicator */
676 #if defined(DUK_USE_INTEGER_LE)
678 #elif defined(DUK_USE_INTEGER_BE)
680 #elif defined(DUK_USE_INTEGER_ME) /* integer mixed endian not really used now */
685 #if defined(DUK_USE_DOUBLE_LE)
687 #elif defined(DUK_USE_DOUBLE_BE)
689 #elif defined(DUK_USE_DOUBLE_ME)
695 /* Packed or unpacked tval */
696 #if defined(DUK_USE_PACKED_TVAL)
701 #if defined(DUK_USE_FASTINT)
705 /* Low memory options */
706 #if defined(DUK_USE_STRTAB_CHAIN)
708 #elif defined(DUK_USE_STRTAB_PROBE)
713 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
716 #if defined(DUK_USE_HEAPPTR16)
719 #if defined(DUK_USE_DATAPTR16)
722 #if defined(DUK_USE_FUNCPTR16)
725 #if defined(DUK_USE_REFCOUNT16)
728 #if defined(DUK_USE_STRHASH16)
731 #if defined(DUK_USE_STRLEN16)
734 #if defined(DUK_USE_BUFLEN16)
737 #if defined(DUK_USE_OBJSIZES16)
740 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
743 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
744 /* XXX: This won't be shown in practice now
745 * because this code is not run when builtins
751 /* Object property allocation layout */
752 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
754 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
756 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
762 /* Alignment guarantee */
763 #if (DUK_USE_ALIGN_BY == 4)
765 #elif (DUK_USE_ALIGN_BY == 8)
767 #elif (DUK_USE_ALIGN_BY == 1)
770 #error invalid DUK_USE_ALIGN_BY
773 /* Architecture, OS, and compiler strings */
778 DUK_USE_COMPILER_STRING
);
779 duk_xdef_prop_stridx(ctx
, DUK_BIDX_DUKTAPE
, DUK_STRIDX_ENV
, DUK_PROPDESC_FLAGS_WC
);
782 * InitJS code - Ecmascript code evaluated from a built-in source
783 * which provides e.g. backward compatibility. User can also provide
784 * JS code to be evaluated at startup.
787 #ifdef DUK_USE_BUILTIN_INITJS
788 /* XXX: compression */
789 DUK_DD(DUK_DDPRINT("running built-in initjs"));
790 duk_eval_string(ctx
, (const char *) duk_initjs_data
); /* initjs data is NUL terminated */
792 #endif /* DUK_USE_BUILTIN_INITJS */
794 #ifdef DUK_USE_USER_INITJS
795 /* XXX: compression (as an option) */
796 DUK_DD(DUK_DDPRINT("running user initjs"));
797 duk_eval_string_noresult(ctx
, (const char *) DUK_USE_USER_INITJS
);
798 #endif /* DUK_USE_USER_INITJS */
801 * Since built-ins are not often extended, compact them.
804 DUK_DD(DUK_DDPRINT("compact built-ins"));
805 for (i
= 0; i
< DUK_NUM_ALL_BUILTINS
; i
++) {
806 duk_hobject_compact_props(thr
, duk_require_hobject(ctx
, i
));
809 DUK_D(DUK_DPRINT("INITBUILTINS END"));
811 #ifdef DUK_USE_DDPRINT
812 for (i
= 0; i
< DUK_NUM_ALL_BUILTINS
; i
++) {
813 DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
814 (long) i
, (duk_heaphdr
*) duk_require_hobject(ctx
, i
)));
819 * Pop built-ins from stack: they are now INCREF'd and
820 * reachable from the builtins[] array or indirectly
821 * through builtins[].
825 DUK_ASSERT_TOP(ctx
, 0);
827 #endif /* DUK_USE_ROM_OBJECTS */
829 DUK_INTERNAL
void duk_hthread_copy_builtin_objects(duk_hthread
*thr_from
, duk_hthread
*thr_to
) {
832 for (i
= 0; i
< DUK_NUM_BUILTINS
; i
++) {
833 thr_to
->builtins
[i
] = thr_from
->builtins
[i
];
834 DUK_HOBJECT_INCREF_ALLOWNULL(thr_to
, thr_to
->builtins
[i
]); /* side effect free */