2 * Compilation and evaluation
5 #include "duk_internal.h"
7 typedef struct duk__compile_raw_args duk__compile_raw_args
;
8 struct duk__compile_raw_args
{
9 duk_size_t src_length
; /* should be first on 64-bit platforms */
10 const duk_uint8_t
*src_buffer
;
14 /* Eval is just a wrapper now. */
15 DUK_EXTERNAL duk_int_t
duk_eval_raw(duk_context
*ctx
, const char *src_buffer
, duk_size_t src_length
, duk_uint_t flags
) {
16 duk_uint_t comp_flags
;
19 DUK_ASSERT_CTX_VALID(ctx
);
21 /* Note: strictness is *not* inherited from the current Duktape/C.
22 * This would be confusing because the current strictness state
23 * depends on whether we're running inside a Duktape/C activation
24 * (= strict mode) or outside of any activation (= non-strict mode).
25 * See tests/api/test-eval-strictness.c for more discussion.
28 /* [ ... source? filename? ] (depends on flags) */
31 comp_flags
|= DUK_COMPILE_EVAL
;
32 rc
= duk_compile_raw(ctx
, src_buffer
, src_length
, comp_flags
); /* may be safe, or non-safe depending on flags */
34 /* [ ... closure/error ] */
36 if (rc
!= DUK_EXEC_SUCCESS
) {
41 duk_push_global_object(ctx
); /* explicit 'this' binding, see GH-164 */
43 if (flags
& DUK_COMPILE_SAFE
) {
44 rc
= duk_pcall_method(ctx
, 0);
46 duk_call_method(ctx
, 0);
47 rc
= DUK_EXEC_SUCCESS
;
50 /* [ ... result/error ] */
53 if (flags
& DUK_COMPILE_NORESULT
) {
60 /* Helper which can be called both directly and with duk_safe_call(). */
61 DUK_LOCAL duk_ret_t
duk__do_compile(duk_context
*ctx
) {
62 duk_hthread
*thr
= (duk_hthread
*) ctx
;
63 duk__compile_raw_args
*comp_args
;
65 duk_small_uint_t comp_flags
;
66 duk_hcompiledfunction
*h_templ
;
68 DUK_ASSERT_CTX_VALID(ctx
);
70 /* Note: strictness is not inherited from the current Duktape/C
71 * context. Otherwise it would not be possible to compile
72 * non-strict code inside a Duktape/C activation (which is
73 * always strict now). See tests/api/test-eval-strictness.c
77 /* [ ... source? filename? &comp_args ] (depends on flags) */
79 comp_args
= (duk__compile_raw_args
*) duk_require_pointer(ctx
, -1);
80 flags
= comp_args
->flags
;
83 /* [ ... source? filename? ] */
85 if (flags
& DUK_COMPILE_NOFILENAME
) {
86 /* Automatic filename: 'eval' or 'input'. */
87 duk_push_hstring_stridx(ctx
, (flags
& DUK_COMPILE_EVAL
) ? DUK_STRIDX_EVAL
: DUK_STRIDX_INPUT
);
90 /* [ ... source? filename ] */
92 if (!comp_args
->src_buffer
) {
93 duk_hstring
*h_sourcecode
;
95 h_sourcecode
= duk_get_hstring(ctx
, -2);
96 if ((flags
& DUK_COMPILE_NOSOURCE
) || /* args incorrect */
97 (h_sourcecode
== NULL
)) { /* e.g. duk_push_string_file_raw() pushed undefined */
98 /* XXX: when this error is caused by a nonexistent
99 * file given to duk_peval_file() or similar, the
100 * error message is not the best possible.
102 DUK_ERROR_API(thr
, DUK_STR_NO_SOURCECODE
);
104 DUK_ASSERT(h_sourcecode
!= NULL
);
105 comp_args
->src_buffer
= (const duk_uint8_t
*) DUK_HSTRING_GET_DATA(h_sourcecode
);
106 comp_args
->src_length
= (duk_size_t
) DUK_HSTRING_GET_BYTELEN(h_sourcecode
);
108 DUK_ASSERT(comp_args
->src_buffer
!= NULL
);
110 /* XXX: unnecessary translation of flags */
112 if (flags
& DUK_COMPILE_EVAL
) {
113 comp_flags
|= DUK_JS_COMPILE_FLAG_EVAL
;
115 if (flags
& DUK_COMPILE_FUNCTION
) {
116 comp_flags
|= DUK_JS_COMPILE_FLAG_EVAL
|
117 DUK_JS_COMPILE_FLAG_FUNCEXPR
;
119 if (flags
& DUK_COMPILE_STRICT
) {
120 comp_flags
|= DUK_JS_COMPILE_FLAG_STRICT
;
123 /* [ ... source? filename ] */
125 duk_js_compile(thr
, comp_args
->src_buffer
, comp_args
->src_length
, comp_flags
);
127 /* [ ... source? func_template ] */
129 if (flags
& DUK_COMPILE_NOSOURCE
) {
135 /* [ ... func_template ] */
137 h_templ
= (duk_hcompiledfunction
*) duk_get_hobject(ctx
, -1);
138 DUK_ASSERT(h_templ
!= NULL
);
139 duk_js_push_closure(thr
,
141 thr
->builtins
[DUK_BIDX_GLOBAL_ENV
],
142 thr
->builtins
[DUK_BIDX_GLOBAL_ENV
],
143 1 /*add_auto_proto*/);
144 duk_remove(ctx
, -2); /* -> [ ... closure ] */
146 /* [ ... closure ] */
151 DUK_EXTERNAL duk_int_t
duk_compile_raw(duk_context
*ctx
, const char *src_buffer
, duk_size_t src_length
, duk_uint_t flags
) {
152 duk__compile_raw_args comp_args_alloc
;
153 duk__compile_raw_args
*comp_args
= &comp_args_alloc
;
155 DUK_ASSERT_CTX_VALID(ctx
);
157 if ((flags
& DUK_COMPILE_STRLEN
) && (src_buffer
!= NULL
)) {
158 /* String length is computed here to avoid multiple evaluation
159 * of a macro argument in the calling side.
161 src_length
= DUK_STRLEN(src_buffer
);
164 comp_args
->src_buffer
= (const duk_uint8_t
*) src_buffer
;
165 comp_args
->src_length
= src_length
;
166 comp_args
->flags
= flags
;
167 duk_push_pointer(ctx
, (void *) comp_args
);
169 /* [ ... source? filename? &comp_args ] (depends on flags) */
171 if (flags
& DUK_COMPILE_SAFE
) {
176 /* Arguments can be: [ source? filename? &comp_args] so that
177 * nargs is 1 to 3. Call site encodes the correct nargs count
178 * directly into flags.
180 nargs
= flags
& 0x07;
181 DUK_ASSERT(nargs
== (1 +
182 ((flags
& DUK_COMPILE_NOSOURCE
) ? 0 : 1) +
183 ((flags
& DUK_COMPILE_NOFILENAME
) ? 0 : 1)));
184 rc
= duk_safe_call(ctx
, duk__do_compile
, nargs
, nrets
);
186 /* [ ... closure ] */
190 (void) duk__do_compile(ctx
);
192 /* [ ... closure ] */
193 return DUK_EXEC_SUCCESS
;