]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_api_compile.c
import 12.2.13 release
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.5.2 / src-separate / duk_api_compile.c
1 /*
2 * Compilation and evaluation
3 */
4
5 #include "duk_internal.h"
6
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;
11 duk_uint_t flags;
12 };
13
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;
17 duk_int_t rc;
18
19 DUK_ASSERT_CTX_VALID(ctx);
20
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.
26 */
27
28 /* [ ... source? filename? ] (depends on flags) */
29
30 comp_flags = 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 */
33
34 /* [ ... closure/error ] */
35
36 if (rc != DUK_EXEC_SUCCESS) {
37 rc = DUK_EXEC_ERROR;
38 goto got_rc;
39 }
40
41 duk_push_global_object(ctx); /* explicit 'this' binding, see GH-164 */
42
43 if (flags & DUK_COMPILE_SAFE) {
44 rc = duk_pcall_method(ctx, 0);
45 } else {
46 duk_call_method(ctx, 0);
47 rc = DUK_EXEC_SUCCESS;
48 }
49
50 /* [ ... result/error ] */
51
52 got_rc:
53 if (flags & DUK_COMPILE_NORESULT) {
54 duk_pop(ctx);
55 }
56
57 return rc;
58 }
59
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;
64 duk_uint_t flags;
65 duk_small_uint_t comp_flags;
66 duk_hcompiledfunction *h_templ;
67
68 DUK_ASSERT_CTX_VALID(ctx);
69
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
74 * for discussion.
75 */
76
77 /* [ ... source? filename? &comp_args ] (depends on flags) */
78
79 comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1);
80 flags = comp_args->flags;
81 duk_pop(ctx);
82
83 /* [ ... source? filename? ] */
84
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);
88 }
89
90 /* [ ... source? filename ] */
91
92 if (!comp_args->src_buffer) {
93 duk_hstring *h_sourcecode;
94
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.
101 */
102 DUK_ERROR_API(thr, DUK_STR_NO_SOURCECODE);
103 }
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);
107 }
108 DUK_ASSERT(comp_args->src_buffer != NULL);
109
110 /* XXX: unnecessary translation of flags */
111 comp_flags = 0;
112 if (flags & DUK_COMPILE_EVAL) {
113 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL;
114 }
115 if (flags & DUK_COMPILE_FUNCTION) {
116 comp_flags |= DUK_JS_COMPILE_FLAG_EVAL |
117 DUK_JS_COMPILE_FLAG_FUNCEXPR;
118 }
119 if (flags & DUK_COMPILE_STRICT) {
120 comp_flags |= DUK_JS_COMPILE_FLAG_STRICT;
121 }
122
123 /* [ ... source? filename ] */
124
125 duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, comp_flags);
126
127 /* [ ... source? func_template ] */
128
129 if (flags & DUK_COMPILE_NOSOURCE) {
130 ;
131 } else {
132 duk_remove(ctx, -2);
133 }
134
135 /* [ ... func_template ] */
136
137 h_templ = (duk_hcompiledfunction *) duk_get_hobject(ctx, -1);
138 DUK_ASSERT(h_templ != NULL);
139 duk_js_push_closure(thr,
140 h_templ,
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 ] */
145
146 /* [ ... closure ] */
147
148 return 1;
149 }
150
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;
154
155 DUK_ASSERT_CTX_VALID(ctx);
156
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.
160 */
161 src_length = DUK_STRLEN(src_buffer);
162 }
163
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);
168
169 /* [ ... source? filename? &comp_args ] (depends on flags) */
170
171 if (flags & DUK_COMPILE_SAFE) {
172 duk_int_t rc;
173 duk_int_t nargs;
174 duk_int_t nrets = 1;
175
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.
179 */
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);
185
186 /* [ ... closure ] */
187 return rc;
188 }
189
190 (void) duk__do_compile(ctx);
191
192 /* [ ... closure ] */
193 return DUK_EXEC_SUCCESS;
194 }