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 = {}) {|_self| ... } ⇒ 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

Yields:

  • (_self)

Yield Parameters:



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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
  yield(self) if block_given?
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



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

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.



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

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



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

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:



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

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

#factoryObject

Returns the ContextFactory used while creating this context.



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

def factory
  @native.getFactory
end

#instruction_limitObject



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

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.



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

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(:restrictable => 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



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

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 !



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

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

#optimization_levelObject



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

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.



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

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)


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

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

#timeout_limitObject



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

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.



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

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(:restrictable => 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.



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

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).



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

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