Class: H8::Context
Class Method Summary collapse
- .can_access?(owner) ⇒ Boolean
-
.delete_handler(object, args) ⇒ Object
:nodoc: Internal handler to properly delete fields/keys from ruby Hashes or OpenStruct.
-
.eval(script, file_name: nil, **kwargs) ⇒ Value
Execute script in a new context with optionally set vars.
-
.secure_call(instance, method, args = nil) ⇒ Object
Secure gate for JS to securely access ruby class properties (methods with no args) and methods.
Instance Method Summary collapse
-
#[]=(name, value) ⇒ Object
Set variable/class for the context.
-
#coffee(script, **kwargs) ⇒ Object
Compile and execute coffeescript, taking same arguments as #eval.
-
#eval(script, max_time: 0, timeout: 0, file_name: nil) {|_self| ... } ⇒ Value
Execute a given script on the current context with optionally limited execution time.
-
#initialize(noglobals: false, **kwargs) ⇒ Context
constructor
Create new context optionally providing variables hash.
-
#safe_proc_call(proc, args) ⇒ Object
This is workaround for buggy rb_proc_call which produces segfaults if proc is not exactly a proc, so we call it like this:.
-
#set_all(**kwargs) ⇒ Object
set variables from keyword arguments to this context see #[]= for details.
Constructor Details
#initialize(noglobals: false, **kwargs) ⇒ Context
Create new context optionally providing variables hash
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/h8/context.rb', line 37 def initialize noglobals: false, **kwargs @idcount = 0 set_all **kwargs _set_var '___create_ruby_class', -> (cls, args) { _do_create_ruby_class cls, args } self[:debug] = -> (*args) { puts args.join(' ') } noglobals or execute_script 'globals.coffee' end |
Class Method Details
.can_access?(owner) ⇒ Boolean
176 177 178 179 |
# File 'lib/h8/context.rb', line 176 def self.can_access?(owner) return true if owner.is_a?(Array.class) owner != Object.class && owner != Kernel && owner != BasicObject.class end |
.delete_handler(object, args) ⇒ Object
:nodoc: Internal handler to properly delete fields/keys from ruby Hashes or OpenStruct
167 168 169 170 171 172 173 174 |
# File 'lib/h8/context.rb', line 167 def self.delete_handler object, args name = args[0] if object.is_a?(OpenStruct) object.delete_field name else object.delete name end end |
.eval(script, file_name: nil, **kwargs) ⇒ Value
Execute script in a new context with optionally set vars. @see H8#set_all
94 95 96 |
# File 'lib/h8/context.rb', line 94 def self.eval script, file_name: nil, ** kwargs Context.new(** kwargs).eval script, file_name: file_name end |
.secure_call(instance, method, args = nil) ⇒ Object
Secure gate for JS to securely access ruby class properties (methods with no args) and methods. This class implements security policy. Overriding this method could breach security and provide full access to ruby object trees.
It has very complex logic so the security model update should be done somehow else.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/h8/context.rb', line 104 def self.secure_call instance, method, args=nil # p [:sc, instance, method, args] if instance.is_a?(Array) method == 'select' and method = '_select_js' end method = method.to_sym begin m = instance.public_method(method) owner = m.owner if can_access?(owner) return m.call(*args) if method[0] == '[' || method[-1] == '=' if m.arity != 0 return ProcGate.new( -> (*args) { m.call *args } ) else return m.call end end rescue NameError # No exact method, calling []/[]= if any method, args = if method[-1] == '=' [:[]=, [method[0..-2].to_s, args[0]]] else [:[], [method.to_s]] end begin m = instance.public_method(method) if can_access?(owner) if method == :[] if instance.is_a?(Hash) return m.call(*args) || m.call(args[0].to_sym) else return m.call(*args) end else return m.call(*args) end end rescue NameError # It means there is no [] or []=, e.g. undefined end end H8::Undefined end |
Instance Method Details
#[]=(name, value) ⇒ Object
Set variable/class for the context. It can set variable to hold:
* primitive type (like string, integer, nil, float and like) - by value!
* any other ruby object - by reference
* ruby Class - creating a javascript constructor function that creates ruby
class instance (any arguments) and gates it to use with js.
64 65 66 |
# File 'lib/h8/context.rb', line 64 def []= name, value set_all name.to_sym => value end |
#coffee(script, **kwargs) ⇒ Object
Compile and execute coffeescript, taking same arguments as #eval.
If you need to execute same script more than once consider first H8::Coffee.compile and cache compiled script.
87 88 89 |
# File 'lib/h8/context.rb', line 87 def coffee script, ** kwargs eval Coffee.compile script, ** kwargs end |
#eval(script, max_time: 0, timeout: 0, file_name: nil) {|_self| ... } ⇒ Value
Execute a given script on the current context with optionally limited execution time.
77 78 79 80 81 |
# File 'lib/h8/context.rb', line 77 def eval script, max_time: 0, timeout: 0, file_name: nil timeout = max_time * 1000 if max_time > 0 yield(self) if block_given? _eval script, timeout.to_i, file_name end |
#safe_proc_call(proc, args) ⇒ Object
This is workaround for buggy rb_proc_call which produces segfaults if proc is not exactly a proc, so we call it like this:
150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/h8/context.rb', line 150 def safe_proc_call proc, args if proc.respond_to?(:call) proc.call(*args) else if args.length == 0 proc # Popular bug: call no-arg method not like a property else raise NoMethodError, "Invalid callable" end end # proc.is_a?(Array) ? proc : proc.call(*args) end |
#set_all(**kwargs) ⇒ Object
set variables from keyword arguments to this context see #[]= for details
53 54 55 56 57 |
# File 'lib/h8/context.rb', line 53 def set_all **kwargs kwargs.each { |name, value| set_var(name.to_s, value) } end |