Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duktape-1.5.2/src-separate/duk_bi_function.c
Go to the documentation of this file.
1/*
2 * Function built-ins
3 */
4
5#include "duk_internal.h"
6
8 duk_hthread *thr = (duk_hthread *) ctx;
9 duk_hstring *h_sourcecode;
10 duk_idx_t nargs;
11 duk_idx_t i;
12 duk_small_uint_t comp_flags;
14 duk_hobject *outer_lex_env;
15 duk_hobject *outer_var_env;
16
17 /* normal and constructor calls have identical semantics */
18
19 nargs = duk_get_top(ctx);
20 for (i = 0; i < nargs; i++) {
21 duk_to_string(ctx, i);
22 }
23
24 if (nargs == 0) {
25 duk_push_string(ctx, "");
26 duk_push_string(ctx, "");
27 } else if (nargs == 1) {
28 /* XXX: cover this with the generic >1 case? */
29 duk_push_string(ctx, "");
30 } else {
31 duk_insert(ctx, 0); /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
32 duk_push_string(ctx, ",");
33 duk_insert(ctx, 1);
34 duk_join(ctx, nargs - 1);
35 }
36
37 /* [ body formals ], formals is comma separated list that needs to be parsed */
38
39 DUK_ASSERT_TOP(ctx, 2);
40
41 /* XXX: this placeholder is not always correct, but use for now.
42 * It will fail in corner cases; see test-dev-func-cons-args.js.
43 */
44 duk_push_string(ctx, "function(");
45 duk_dup(ctx, 1);
46 duk_push_string(ctx, "){");
47 duk_dup(ctx, 0);
48 duk_push_string(ctx, "}");
49 duk_concat(ctx, 5);
50
51 /* [ body formals source ] */
52
53 DUK_ASSERT_TOP(ctx, 3);
54
55 /* strictness is not inherited, intentional */
57
58 duk_push_hstring_stridx(ctx, DUK_STRIDX_COMPILE); /* XXX: copy from caller? */ /* XXX: ignored now */
59 h_sourcecode = duk_require_hstring(ctx, -2);
61 (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
62 (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
63 comp_flags);
64 func = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
65 DUK_ASSERT(func != NULL);
67
68 /* [ body formals source template ] */
69
70 /* only outer_lex_env matters, as functions always get a new
71 * variable declaration environment.
72 */
73
74 outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
75 outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
76
77 duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
78
79 /* [ body formals source template closure ] */
80
81 return 1;
82}
83
85 /* ignore arguments, return undefined (E5 Section 15.3.4) */
86 DUK_UNREF(ctx);
87 return 0;
88}
89
91 duk_tval *tv;
92
93 /*
94 * E5 Section 15.3.4.2 places few requirements on the output of
95 * this function:
96 *
97 * - The result is an implementation dependent representation
98 * of the function; in particular
99 *
100 * - The result must follow the syntax of a FunctionDeclaration.
101 * In particular, the function must have a name (even in the
102 * case of an anonymous function or a function with an empty
103 * name).
104 *
105 * - Note in particular that the output does NOT need to compile
106 * into anything useful.
107 */
108
109
110 /* XXX: faster internal way to get this */
111 duk_push_this(ctx);
112 tv = duk_get_tval(ctx, -1);
113 DUK_ASSERT(tv != NULL);
114
115 if (DUK_TVAL_IS_OBJECT(tv)) {
117 const char *func_name;
118
119 /* Function name: missing/undefined is mapped to empty string,
120 * otherwise coerce to string.
121 */
122 /* XXX: currently no handling for non-allowed identifier characters,
123 * e.g. a '{' in the function name.
124 */
126 if (duk_is_undefined(ctx, -1)) {
127 func_name = "";
128 } else {
129 func_name = duk_to_string(ctx, -1);
130 DUK_ASSERT(func_name != NULL);
131 }
132
133 /* Indicate function type in the function body using a dummy
134 * directive.
135 */
137 duk_push_sprintf(ctx, "function %s() {\"ecmascript\"}", (const char *) func_name);
138 } else if (DUK_HOBJECT_HAS_NATIVEFUNCTION(obj)) {
139 duk_push_sprintf(ctx, "function %s() {\"native\"}", (const char *) func_name);
140 } else if (DUK_HOBJECT_HAS_BOUND(obj)) {
141 duk_push_sprintf(ctx, "function %s() {\"bound\"}", (const char *) func_name);
142 } else {
143 goto type_error;
144 }
145 } else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
147 } else {
148 goto type_error;
149 }
150
151 return 1;
152
153 type_error:
154 return DUK_RET_TYPE_ERROR;
155}
156
158 duk_idx_t len;
159 duk_idx_t i;
160
161 DUK_ASSERT_TOP(ctx, 2); /* not a vararg function */
162
163 duk_push_this(ctx);
164 if (!duk_is_callable(ctx, -1)) {
165 DUK_DDD(DUK_DDDPRINT("func is not callable"));
166 goto type_error;
167 }
168 duk_insert(ctx, 0);
169 DUK_ASSERT_TOP(ctx, 3);
170
171 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argArray=%!iT",
172 (duk_tval *) duk_get_tval(ctx, 0),
173 (duk_tval *) duk_get_tval(ctx, 1),
174 (duk_tval *) duk_get_tval(ctx, 2)));
175
176 /* [ func thisArg argArray ] */
177
178 if (duk_is_null_or_undefined(ctx, 2)) {
179 DUK_DDD(DUK_DDDPRINT("argArray is null/undefined, no args"));
180 len = 0;
181 } else if (!duk_is_object(ctx, 2)) {
182 goto type_error;
183 } else {
184 DUK_DDD(DUK_DDDPRINT("argArray is an object"));
185
186 /* XXX: make this an internal helper */
188 len = (duk_idx_t) duk_to_uint32(ctx, -1); /* ToUint32() coercion required */
189 duk_pop(ctx);
190
191 duk_require_stack(ctx, len);
192
193 DUK_DDD(DUK_DDDPRINT("argArray length is %ld", (long) len));
194 for (i = 0; i < len; i++) {
195 duk_get_prop_index(ctx, 2, i);
196 }
197 }
198 duk_remove(ctx, 2);
199 DUK_ASSERT_TOP(ctx, 2 + len);
200
201 /* [ func thisArg arg1 ... argN ] */
202
203 DUK_DDD(DUK_DDDPRINT("apply, func=%!iT, thisArg=%!iT, len=%ld",
204 (duk_tval *) duk_get_tval(ctx, 0),
205 (duk_tval *) duk_get_tval(ctx, 1),
206 (long) len));
207 duk_call_method(ctx, len);
208 return 1;
209
210 type_error:
211 return DUK_RET_TYPE_ERROR;
212}
213
215 duk_idx_t nargs;
216
217 /* Step 1 is not necessary because duk_call_method() will take
218 * care of it.
219 */
220
221 /* vararg function, thisArg needs special handling */
222 nargs = duk_get_top(ctx); /* = 1 + arg count */
223 if (nargs == 0) {
225 nargs++;
226 }
227 DUK_ASSERT(nargs >= 1);
228
229 /* [ thisArg arg1 ... argN ] */
230
231 duk_push_this(ctx); /* 'func' in the algorithm */
232 duk_insert(ctx, 0);
233
234 /* [ func thisArg arg1 ... argN ] */
235
236 DUK_DDD(DUK_DDDPRINT("func=%!iT, thisArg=%!iT, argcount=%ld, top=%ld",
237 (duk_tval *) duk_get_tval(ctx, 0),
238 (duk_tval *) duk_get_tval(ctx, 1),
239 (long) (nargs - 1),
240 (long) duk_get_top(ctx)));
241 duk_call_method(ctx, nargs - 1);
242 return 1;
243}
244
245/* XXX: the implementation now assumes "chained" bound functions,
246 * whereas "collapsed" bound functions (where there is ever only
247 * one bound function which directly points to a non-bound, final
248 * function) would require a "collapsing" implementation which
249 * merges argument lists etc here.
250 */
252 duk_hobject *h_bound;
253 duk_hobject *h_target;
254 duk_idx_t nargs;
255 duk_idx_t i;
256
257 /* vararg function, careful arg handling (e.g. thisArg may not be present) */
258 nargs = duk_get_top(ctx); /* = 1 + arg count */
259 if (nargs == 0) {
261 nargs++;
262 }
263 DUK_ASSERT(nargs >= 1);
264
265 duk_push_this(ctx);
266 if (!duk_is_callable(ctx, -1)) {
267 DUK_DDD(DUK_DDDPRINT("func is not callable"));
268 goto type_error;
269 }
270
271 /* [ thisArg arg1 ... argN func ] (thisArg+args == nargs total) */
272 DUK_ASSERT_TOP(ctx, nargs + 1);
273
274 /* create bound function object */
281 h_bound = duk_get_hobject(ctx, -1);
282 DUK_ASSERT(h_bound != NULL);
283
284 /* [ thisArg arg1 ... argN func boundFunc ] */
285 duk_dup(ctx, -2); /* func */
287
288 duk_dup(ctx, 0); /* thisArg */
290
291 duk_push_array(ctx);
292
293 /* [ thisArg arg1 ... argN func boundFunc argArray ] */
294
295 for (i = 0; i < nargs - 1; i++) {
296 duk_dup(ctx, 1 + i);
297 duk_put_prop_index(ctx, -2, i);
298 }
300
301 /* [ thisArg arg1 ... argN func boundFunc ] */
302
303 /* bound function 'length' property is interesting */
304 h_target = duk_get_hobject(ctx, -2);
305 if (h_target == NULL || /* lightfunc */
307 /* For lightfuncs, simply read the virtual property. */
308 duk_int_t tmp;
310 tmp = duk_to_int(ctx, -1) - (nargs - 1); /* step 15.a */
311 duk_pop(ctx);
312 duk_push_int(ctx, (tmp < 0 ? 0 : tmp));
313 } else {
314 duk_push_int(ctx, 0);
315 }
316 duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE); /* attrs in E5 Section 15.3.5.1 */
317
318 /* caller and arguments must use the same thrower, [[ThrowTypeError]] */
321
322 /* these non-standard properties are copied for convenience */
323 /* XXX: 'copy properties' API call? */
328
329 /* The 'strict' flag is copied to get the special [[Get]] of E5.1
330 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
331 * function. Not sure if this is correct, because the specification
332 * is a bit ambiguous on this point but it would make sense.
333 */
334 if (h_target == NULL) {
335 /* Lightfuncs are always strict. */
336 DUK_HOBJECT_SET_STRICT(h_bound);
337 } else if (DUK_HOBJECT_HAS_STRICT(h_target)) {
338 DUK_HOBJECT_SET_STRICT(h_bound);
339 }
340 DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(ctx, -1)));
341
342 return 1;
343
344 type_error:
345 return DUK_RET_TYPE_ERROR;
346}
unsigned int duk_small_uint_t
duk_small_int_t duk_ret_t
duk_int_fast32_t duk_int_t
DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count)
DUK_EXTERNAL const char * duk_push_string(duk_context *ctx, const char *str)
#define DUK_HSTRING_GET_DATA(x)
DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_FLAG_CONSTRUCTABLE
#define DUK_HOBJECT_HAS_BOUND(h)
DUK_EXTERNAL void duk_push_this(duk_context *ctx)
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
#define DUK_STRIDX_LC_ARGUMENTS
DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_context *ctx, duk_tval *tv)
#define DUK_TVAL_GET_OBJECT(tv)
DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
#define DUK_HOBJECT_IS_COMPILEDFUNCTION(h)
DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr, duk_hcompiledfunction *fun_temp, duk_hobject *outer_var_env, duk_hobject *outer_lex_env, duk_bool_t add_auto_proto)
#define DUK_TVAL_IS_OBJECT(tv)
#define DUK_BIDX_FUNCTION_PROTOTYPE
#define DUK_PROPDESC_FLAGS_NONE
DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_context *ctx, duk_small_int_t stridx)
#define DUK_HOBJECT_CLASS_FUNCTION
DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra)
DUK_EXTERNAL void duk_remove(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val)
#define DUK_HOBJECT_CLASS_AS_FLAGS(v)
DUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags)
#define DUK_HOBJECT_SET_STRICT(h)
DUK_EXTERNAL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_FLAG_BOUND
#define DUK_TVAL_IS_LIGHTFUNC(tv)
#define DUK_HSTRING_GET_BYTELEN(x)
DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index)
DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index)
DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx)
#define DUK_JS_COMPILE_FLAG_FUNCEXPR
DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_index, duk_uarridx_t arr_index)
#define DUK_HOBJECT_HAS_NATIVEFUNCTION(h)
DUK_EXTERNAL void duk_push_undefined(duk_context *ctx)
#define DUK_STRIDX_INT_TARGET
DUK_EXTERNAL void duk_call_method(duk_context *ctx, duk_idx_t nargs)
DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t index)
#define DUK_PROPDESC_FLAGS_WC
DUK_EXTERNAL const char * duk_push_sprintf(duk_context *ctx, const char *fmt,...)
#define DUK_ASSERT_TOP(ctx, n)
DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags)
#define DUK_HOBJECT_FLAG_EXTENSIBLE
DUK_INTERNAL_DECL duk_idx_t duk_push_object_helper(duk_context *ctx, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx)
DUK_EXTERNAL duk_bool_t duk_is_null_or_undefined(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL void duk_pop(duk_context *ctx)
DUK_INTERNAL_DECL duk_hobject * duk_get_hobject(duk_context *ctx, duk_idx_t index)
DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx)
#define DUK_HOBJECT_GET_CLASS_NUMBER(h)
DUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx, duk_small_uint_t desc_flags)
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_HAS_STRICT(h)
DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_HAS_COMPILEDFUNCTION(h)
DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count)
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_context *ctx, duk_idx_t index)
#define duk_is_callable(ctx, index)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_context *ctx)
DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_context *ctx)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx)
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx)
#define NULL
Definition gmacros.h:924
duk_hobject * builtins[DUK_NUM_BUILTINS]