Class: Rhino::Context

Inherits:
Object show all
Defined in:
lib/rhino/context.rb

Overview

Overview

All Javascript must be executed in a context which represents the execution environment in
which scripts will run. The environment consists of the standard javascript objects
and functions like Object, String, Array, etc... as well as any objects or functions which
have been defined in it. e.g.

 Context.open do |cxt|
   cxt['num'] = 5
   cxt.eval('num + 5') #=> 10
 end

Multiple Contexts.

The same object may appear in any number of contexts, but only one context may be executing javascript code in any given thread. If a new context is opened in a thread in which a context is already opened, the second context will “mask” the old context e.g.

six = 6
Context.open do |cxt|
  cxt['num'] = 5
  cxt.eval('num') # => 5
  Context.open do |cxt|
    cxt['num'] = 10
    cxt.eval('num') # => 10
    cxt.eval('++num') # => 11
  end
  cxt.eval('num') # => 5
end

Notes

While there are many similarities between Rhino::Context and Java::org.mozilla.javascript.Context, they are not the same thing and should not be confused.

Constant Summary collapse

@@default_factory =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Context

Create a new javascript environment for executing javascript and ruby code.

  • :sealed - if this is true, then the standard objects such as Object, Function, Array will not be able to be modified

  • :with - use this ruby object as the root scope for all javascript that is evaluated

  • :java - if true, java packages will be accessible from within javascript



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rhino/context.rb', line 67

def initialize(options = {}) #:nodoc:
  factory = options[:factory] || 
    (options[:restrictable] ? RestrictableContextFactory.instance : self.class.default_factory)
  factory.call do |context|
    @native = context
    @global = @native.initStandardObjects(nil, options[:sealed] == true)
    if with = options[:with]
      @scope = Rhino.to_javascript(with)
      @scope.setParentScope(@global)
    else
      @scope = @global
    end
    unless options[:java]
      for package in ["Packages", "java", "javax", "org", "com", "edu", "net"]
        @global.delete(package)
      end
    end
  end
end

Instance Attribute Details

#scopeObject (readonly)

Returns the value of attribute scope.



61
62
63
# File 'lib/rhino/context.rb', line 61

def scope
  @scope
end

Class Method Details

.default_factoryObject



53
54
55
# File 'lib/rhino/context.rb', line 53

def self.default_factory
  @@default_factory ||= ContextFactory.new
end

.default_factory=(factory) ⇒ Object



57
58
59
# File 'lib/rhino/context.rb', line 57

def self.default_factory=(factory)
  @@default_factory = factory
end

.eval(javascript) ⇒ Object



46
47
48
# File 'lib/rhino/context.rb', line 46

def eval(javascript)
  new.eval(javascript)
end

.open(options = {}, &block) ⇒ Object

initalize a new context with a fresh set of standard objects. All operations on the context should be performed in the block that is passed.



42
43
44
# File 'lib/rhino/context.rb', line 42

def open(options = {}, &block)
  new(options).open(&block)
end

Instance Method Details

#[](key) ⇒ Object

Read a value from the global scope of this context



93
94
95
# File 'lib/rhino/context.rb', line 93

def [](key)
  @scope[key]
end

#[]=(key, val) ⇒ Object

Set a value in the global scope of this context. This value will be visible to all the javascript that is executed in this context.



99
100
101
# File 'lib/rhino/context.rb', line 99

def []=(key, val)
  @scope[key] = val
end

#eval(source, source_name = "<eval>", line_number = 1) ⇒ Object

Evaluate a string of javascript in this context:

  • source - the javascript source code to evaluate. This can be either a string or an IO object.

  • source_name - associated name for this source code. Mainly useful for backtraces.

  • line_number - associate this number with the first line of executing source. Mainly useful for backtraces



107
108
109
110
111
112
113
114
115
116
# File 'lib/rhino/context.rb', line 107

def eval(source, source_name = "<eval>", line_number = 1)
  open do
    if IO === source || StringIO === source
      result = @native.evaluateReader(@scope, IOReader.new(source), source_name, line_number, nil)
    else
      result = @native.evaluateString(@scope, source.to_s, source_name, line_number, nil)
    end
    Rhino.to_ruby(result)
  end
end

#evaluate(*args) ⇒ Object

:nodoc:



118
119
120
# File 'lib/rhino/context.rb', line 118

def evaluate(*args) # :nodoc:
  eval(*args) # an alias
end

#factoryObject

Returns the ContextFactory used while creating this context.



88
89
90
# File 'lib/rhino/context.rb', line 88

def factory
  @native.getFactory
end

#instruction_limitObject



140
141
142
# File 'lib/rhino/context.rb', line 140

def instruction_limit
  restrictable? ? @native.instruction_limit : false
end

#instruction_limit=(limit) ⇒ Object

Set the maximum number of instructions that this context will execute. If this instruction limit is exceeded, then a #Rhino::RunawayScriptError will be raised.



147
148
149
150
151
152
153
154
# File 'lib/rhino/context.rb', line 147

def instruction_limit=(limit)
  if restrictable?
    @native.instruction_limit = limit
  else
    raise "setting an instruction_limit has no effect on this context, use " + 
          "Context.open(:restricted => true) to gain a restrictable instance"
  end
end

#load(filename) ⇒ Object

Read the contents of filename and evaluate it as javascript. Returns the result of evaluating the javascript. e.g.

Context.open do |cxt|

cxt.load("path/to/some/lib.js")

end



129
130
131
132
133
# File 'lib/rhino/context.rb', line 129

def load(filename)
  File.open(filename) do |file|
    evaluate file, filename, 1
  end
end

#open(&block) ⇒ Object

Enter this context for operations. Some methods such as eval() will fail unless this context is open !



217
218
219
220
221
# File 'lib/rhino/context.rb', line 217

def open(&block)
  do_open(&block)
rescue JS::RhinoException => e
  raise Rhino::JSError.new(e)
end

#optimization_levelObject



173
174
175
# File 'lib/rhino/context.rb', line 173

def optimization_level
  @native.getOptimizationLevel
end

#optimization_level=(level) ⇒ Object

Set the optimization level that this context will use. This is sometimes necessary in Rhino, if the bytecode size of the compiled javascript exceeds the 64KB limit. By using the -1 optimization level, you tell Rhino to run in interpretative mode, taking a hit to performance but escaping the Java bytecode limit.



181
182
183
184
185
186
187
188
189
# File 'lib/rhino/context.rb', line 181

def optimization_level=(level)
  if JS::Context.isValidOptimizationLevel(level)
    @native.setOptimizationLevel(level)
    level
  else
    @native.setOptimizationLevel(0)
    nil
  end
end

#restrictable?Boolean

Returns true if this context supports restrictions.

Returns:

  • (Boolean)


136
137
138
# File 'lib/rhino/context.rb', line 136

def restrictable?
  @native.is_a?(RestrictableContextFactory::Context)
end

#timeout_limitObject



156
157
158
# File 'lib/rhino/context.rb', line 156

def timeout_limit
  restrictable? ? @native.timeout_limit : false
end

#timeout_limit=(limit) ⇒ Object

Set the duration (in seconds e.g. 1.5) this context is allowed to execute. After the timeout passes (no matter if any JS has been evaluated) and this context is still attempted to run code, a #Rhino::ScriptTimeoutError will be raised.



164
165
166
167
168
169
170
171
# File 'lib/rhino/context.rb', line 164

def timeout_limit=(limit)
  if restrictable?
    @native.timeout_limit = limit
  else
    raise "setting an timeout_limit has no effect on this context, use " + 
          "Context.open(:restricted => true) to gain a restrictable instance"
  end
end

#versionObject

Get the JS interpreter version. Returns a number e.g. 1.7, nil if unknown and 0 for default.



193
194
195
196
197
198
199
# File 'lib/rhino/context.rb', line 193

def version
  case const_value = @native.getLanguageVersion
    when -1 then nil # VERSION_UNKNOWN
    when  0 then 0 # VERSION_DEFAULT
    else const_value / 100.0 # VERSION_1_1 (1.1 = 110 / 100)
  end
end

#version=(version) ⇒ Object

Sets interpreter mode a.k.a. JS language version e.g. 1.7 (if supported).



202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/rhino/context.rb', line 202

def version=(version)
  const = version.to_s.gsub('.', '_').upcase
  const = "VERSION_#{const}" if const[0, 7] != 'VERSION'
  if JS::Context.constants.find { |c| c.to_s == const }
    const_value = JS::Context.const_get(const)
    @native.setLanguageVersion(const_value)
    const_value
  else
    @native.setLanguageVersion(JS::Context::VERSION_DEFAULT)
    nil
  end
end