mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Avoid exposure for REnv objects
The `REnv` object is difficult to deal with, and it would be ideal if the user did not have to manipulate it directly.
In some previous situations, it was necessary to call `mrb_env_unshare()`, a non-API function, after `mrb_load_string()` or similar.
With this patch, it is no longer necessary for users to use `mrb_env_unshare()` directly, as it is now handled internally simply by using the `mrb_vm_ci_env_clear()` function.
Also, `mrb_vm_ci_env_set()` is demoted from the `MRB_API` function for the same reason.
ref. commit 1ab3da6f08
This commit is contained in:
+36
-2
@@ -136,12 +136,46 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
|
||||
|
||||
MRB_API mrb_value mrb_load_proc(mrb_state *mrb, const struct RProc *proc);
|
||||
|
||||
/**
|
||||
* It can be used to isolate top-level scopes referenced by blocks generated by
|
||||
* `mrb_load_string_cxt()` or similar called before entering the mruby VM (e.g. from `main()`).
|
||||
* In that case, the `ci` parameter should be `mrb->c->cibase`.
|
||||
*
|
||||
* #include <mruby.h>
|
||||
* #include <mruby/compile.h>
|
||||
* #include <mruby/proc.h>
|
||||
*
|
||||
* int
|
||||
* main(int argc, char **argv)
|
||||
* {
|
||||
* mrb_state *mrb;
|
||||
* mrbc_context *cxt;
|
||||
* mrb_value blk, ret;
|
||||
*
|
||||
* mrb = mrb_open();
|
||||
* cxt = mrbc_context_new(mrb);
|
||||
* blk = mrb_load_string_cxt(mrb, "x, y, z = 1, 2, 3; proc { [x, y, z] }", cxt);
|
||||
* mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
|
||||
* mrb_load_string_cxt(mrb, "x, y, z = 4, 5, 6", cxt);
|
||||
* ret = mrb_funcall(mrb, blk, "call", 0);
|
||||
* mrb_p(mrb, ret); // => [1, 2, 3]
|
||||
* // => [4, 5, 6] if `mrb_vm_ci_env_clear()` is commented out
|
||||
* mrbc_context_free(mrb, cxt);
|
||||
* mrb_close(mrb);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* The top-level local variable names stored in `mrbc_context` are retained.
|
||||
* Use also `mrbc_cleanup_local_variables()` at the same time, if necessary.
|
||||
*/
|
||||
MRB_API void mrb_vm_ci_env_clear(mrb_state *mrb, mrb_callinfo *ci);
|
||||
|
||||
void mrb_vm_ci_proc_set(mrb_callinfo *ci, const struct RProc *p);
|
||||
struct RClass * mrb_vm_ci_target_class(const mrb_callinfo *ci);
|
||||
void mrb_vm_ci_target_class_set(mrb_callinfo *ci, struct RClass *tc);
|
||||
struct REnv * mrb_vm_ci_env(const mrb_callinfo *ci);
|
||||
MRB_API void mrb_vm_ci_env_clear(mrb_callinfo *ci);
|
||||
MRB_API void mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e);
|
||||
void mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
|
||||
+1
-3
@@ -223,9 +223,7 @@ module MRuby
|
||||
f.puts %Q[ mrb_close(mrb);]
|
||||
f.puts %Q[ exit(EXIT_FAILURE);]
|
||||
f.puts %Q[ }]
|
||||
f.puts %Q[ struct REnv *e = mrb_vm_ci_env(mrb->c->cibase);]
|
||||
f.puts %Q[ mrb_vm_ci_env_clear(mrb->c->cibase);]
|
||||
f.puts %Q[ mrb_env_unshare(mrb, e, FALSE);]
|
||||
f.puts %Q[ mrb_vm_ci_env_clear(mrb, mrb->c->cibase);]
|
||||
end
|
||||
f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
|
||||
f.puts %Q[}]
|
||||
|
||||
@@ -508,7 +508,6 @@ main(int argc, char **argv)
|
||||
|
||||
/* Load libraries */
|
||||
for (i = 0; i < args.libc; i++) {
|
||||
struct REnv *e;
|
||||
FILE *lfp = fopen(args.libv[i], "r");
|
||||
if (lfp == NULL) {
|
||||
printf("Cannot open library file. (%s)\n", args.libv[i]);
|
||||
@@ -517,9 +516,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
mrb_load_file_cxt(mrb, lfp, cxt);
|
||||
fclose(lfp);
|
||||
e = mrb_vm_ci_env(mrb->c->cibase);
|
||||
mrb_vm_ci_env_set(mrb->c->cibase, NULL);
|
||||
mrb_env_unshare(mrb, e, FALSE);
|
||||
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
|
||||
mrbc_cleanup_local_variables(mrb, cxt);
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,6 @@ main(int argc, char **argv)
|
||||
|
||||
/* Load libraries */
|
||||
for (i = 0; i < args.libc; i++) {
|
||||
struct REnv *e;
|
||||
FILE *lfp = fopen(args.libv[i], "rb");
|
||||
if (lfp == NULL) {
|
||||
fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
|
||||
@@ -342,9 +341,7 @@ main(int argc, char **argv)
|
||||
v = mrb_load_detect_file_cxt(mrb, lfp, c);
|
||||
}
|
||||
fclose(lfp);
|
||||
e = mrb_vm_ci_env(mrb->c->cibase);
|
||||
mrb_vm_ci_env_set(mrb->c->cibase, NULL);
|
||||
mrb_env_unshare(mrb, e, FALSE);
|
||||
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
|
||||
mrbc_cleanup_local_variables(mrb, c);
|
||||
}
|
||||
|
||||
|
||||
@@ -318,22 +318,19 @@ ci_env_set(mrb_callinfo *ci, struct REnv *e)
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
void
|
||||
mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e)
|
||||
{
|
||||
ci_env_set(ci, e);
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_vm_ci_env_clear(mrb_callinfo *ci)
|
||||
mrb_vm_ci_env_clear(mrb_state *mrb, mrb_callinfo *ci)
|
||||
{
|
||||
if (ci->u.env) {
|
||||
if (ci->u.env->tt == MRB_TT_ENV) {
|
||||
ci->u.target_class = ci->u.env->c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ci->u.env = NULL;
|
||||
struct REnv *e = ci->u.env;
|
||||
if (e && e->tt == MRB_TT_ENV) {
|
||||
ci->u.target_class = e->c;
|
||||
mrb_env_unshare(mrb, e, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user