1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
#if !defined(LIQUID_CONTEXT_H)
#define LIQUID_CONTEXT_H
#include "resource_limits.h"
typedef struct context {
VALUE self;
VALUE environments;
VALUE static_environments;
VALUE scopes;
VALUE strainer;
VALUE filter_methods;
VALUE interrupts;
VALUE resource_limits_obj;
resource_limits_t *resource_limits;
VALUE global_filter;
bool strict_variables;
bool strict_filters;
} context_t;
void liquid_define_context(void);
void context_internal_init(VALUE context_obj, context_t *context);
void context_mark(context_t *context);
VALUE context_find_variable(context_t *context, VALUE key, VALUE raise_on_not_found);
void context_maybe_raise_undefined_variable(VALUE self, VALUE key);
extern ID id_aset, id_set_context;
#ifndef RB_SPECIAL_CONST_P
// RB_SPECIAL_CONST_P added in Ruby 2.3
#define RB_SPECIAL_CONST_P SPECIAL_CONST_P
#endif
inline static VALUE value_to_liquid_and_set_context(VALUE value, VALUE context_to_set)
{
// Scalar type stored directly in the VALUE, these all have a #to_liquid
// that returns self, and should have no #context= method
if (RB_SPECIAL_CONST_P(value))
return value;
VALUE klass = RBASIC_CLASS(value);
// More basic types having #to_liquid of self and no #context=
if (klass == rb_cString || klass == rb_cArray || klass == rb_cHash)
return value;
value = rb_funcall(value, id_to_liquid, 0);
if (rb_respond_to(value, id_set_context))
rb_funcall(value, id_set_context, 1, context_to_set);
return value;
}
inline static VALUE materialize_proc(VALUE context, VALUE scope, VALUE key, VALUE value)
{
if (scope != Qnil && rb_obj_is_proc(value) && rb_respond_to(scope, id_aset)) {
if (rb_proc_arity(value) == 1) {
value = rb_funcall(value, id_call, 1, context);
} else {
value = rb_funcall(value, id_call, 0);
}
rb_funcall(scope, id_aset, 2, key, value);
}
return value;
}
#endif
|