]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
11fdf7f2 | 28 | /* [ ... source? filename? ] (depends on flags) */ |
7c673cae FG |
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 | ||
11fdf7f2 | 77 | /* [ ... source? filename? &comp_args ] (depends on flags) */ |
7c673cae FG |
78 | |
79 | comp_args = (duk__compile_raw_args *) duk_require_pointer(ctx, -1); | |
80 | flags = comp_args->flags; | |
81 | duk_pop(ctx); | |
82 | ||
11fdf7f2 TL |
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 | ||
7c673cae FG |
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 | */ | |
11fdf7f2 | 102 | DUK_ERROR_API(thr, DUK_STR_NO_SOURCECODE); |
7c673cae FG |
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], | |
11fdf7f2 TL |
142 | thr->builtins[DUK_BIDX_GLOBAL_ENV], |
143 | 1 /*add_auto_proto*/); | |
7c673cae FG |
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 | ||
11fdf7f2 | 169 | /* [ ... source? filename? &comp_args ] (depends on flags) */ |
7c673cae FG |
170 | |
171 | if (flags & DUK_COMPILE_SAFE) { | |
172 | duk_int_t rc; | |
173 | duk_int_t nargs; | |
174 | duk_int_t nrets = 1; | |
175 | ||
11fdf7f2 TL |
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))); | |
7c673cae FG |
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 | } |