1 /*
2  *  Duktape built-ins
3  *
4  *  Size optimization note: it might seem that vararg multipurpose functions
5  *  like fin(), enc(), and dec() are not very size optimal, but using a single
6  *  user-visible ECMAScript function saves a lot of run-time footprint; each
7  *  Function instance takes >100 bytes.  Using a shared native helper and a
8  *  'magic' value won't save much if there are multiple Function instances
9  *  anyway.
10  */
11 
12 #include "duk_internal.h"
13 
14 #if defined(DUK_USE_DUKTAPE_BUILTIN)
15 
duk_bi_duktape_object_info(duk_hthread * thr)16 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
17 	duk_inspect_value(thr, -1);
18 	return 1;
19 }
20 
duk_bi_duktape_object_act(duk_hthread * thr)21 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
22 	duk_int_t level;
23 
24 	level = duk_to_int(thr, 0);
25 	duk_inspect_callstack_entry(thr, level);
26 	return 1;
27 }
28 
duk_bi_duktape_object_gc(duk_hthread * thr)29 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
30 	duk_small_uint_t flags;
31 
32 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
33 	duk_heap_mark_and_sweep(thr->heap, flags);
34 
35 	/* XXX: Not sure what the best return value would be in the API.
36 	 * Return true for now.
37 	 */
38 	duk_push_true(thr);
39 	return 1;
40 }
41 
42 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)43 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
44 	(void) duk_require_hobject(thr, 0);
45 	if (duk_get_top(thr) >= 2) {
46 		/* Set: currently a finalizer is disabled by setting it to
47 		 * undefined; this does not remove the property at the moment.
48 		 * The value could be type checked to be either a function
49 		 * or something else; if something else, the property could
50 		 * be deleted.  Must use duk_set_finalizer() to keep
51 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
52 		 */
53 		duk_set_top(thr, 2);
54 		duk_set_finalizer(thr, 0);
55 		return 0;
56 	} else {
57 		/* Get. */
58 		DUK_ASSERT(duk_get_top(thr) == 1);
59 		duk_get_finalizer(thr, 0);
60 		return 1;
61 	}
62 }
63 #endif  /* DUK_USE_FINALIZER_SUPPORT */
64 
duk_bi_duktape_object_enc(duk_hthread * thr)65 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
66 	duk_hstring *h_str;
67 
68 	/* Vararg function: must be careful to check/require arguments.
69 	 * The JSON helpers accept invalid indices and treat them like
70 	 * non-existent optional parameters.
71 	 */
72 
73 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
74 	duk_require_valid_index(thr, 1);
75 
76 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
77 		duk_set_top(thr, 2);
78 		duk_hex_encode(thr, 1);
79 		DUK_ASSERT_TOP(thr, 2);
80 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
81 		duk_set_top(thr, 2);
82 		duk_base64_encode(thr, 1);
83 		DUK_ASSERT_TOP(thr, 2);
84 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
85 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
86 		duk_bi_json_stringify_helper(thr,
87 		                             1 /*idx_value*/,
88 		                             2 /*idx_replacer*/,
89 		                             3 /*idx_space*/,
90 		                             DUK_JSON_FLAG_EXT_CUSTOM |
91 		                             DUK_JSON_FLAG_ASCII_ONLY |
92 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
93 #endif
94 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
95 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
96 		duk_bi_json_stringify_helper(thr,
97 		                             1 /*idx_value*/,
98 		                             2 /*idx_replacer*/,
99 		                             3 /*idx_space*/,
100 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
101 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
102 #endif
103 	} else {
104 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
105 	}
106 	return 1;
107 }
108 
duk_bi_duktape_object_dec(duk_hthread * thr)109 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
110 	duk_hstring *h_str;
111 
112 	/* Vararg function: must be careful to check/require arguments.
113 	 * The JSON helpers accept invalid indices and treat them like
114 	 * non-existent optional parameters.
115 	 */
116 
117 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
118 	duk_require_valid_index(thr, 1);
119 
120 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
121 		duk_set_top(thr, 2);
122 		duk_hex_decode(thr, 1);
123 		DUK_ASSERT_TOP(thr, 2);
124 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
125 		duk_set_top(thr, 2);
126 		duk_base64_decode(thr, 1);
127 		DUK_ASSERT_TOP(thr, 2);
128 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
129 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
130 		duk_bi_json_parse_helper(thr,
131 		                         1 /*idx_value*/,
132 		                         2 /*idx_replacer*/,
133 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
134 #endif
135 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
136 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
137 		duk_bi_json_parse_helper(thr,
138 		                         1 /*idx_value*/,
139 		                         2 /*idx_replacer*/,
140 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
141 #endif
142 	} else {
143 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
144 	}
145 	return 1;
146 }
147 
148 /*
149  *  Compact an object
150  */
151 
duk_bi_duktape_object_compact(duk_hthread * thr)152 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
153 	DUK_ASSERT_TOP(thr, 1);
154 	duk_compact(thr, 0);
155 	return 1;  /* return the argument object */
156 }
157 
158 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
159