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::OrgMozillaJavascript::Context, they are not the same thing and should not be confused.

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



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/rhino/context.rb', line 58

def initialize(options = {}) #:nodoc:
  ContextFactory.new.call do |native|
    @native = native
    @global = NativeObject.new(@native.initStandardObjects(nil, options[:sealed] == true))
    if with = options[:with]
      @scope = To.javascript(with)
      @scope.setParentScope(@global.j)
    else
      @scope = @global
    end
    unless options[:java]
      for package in ["Packages", "java", "javax", "org", "com", "edu", "net"]
        @global.j.delete(package)
      end
    end
  end
end

Instance Attribute Details

#scopeObject (readonly)

Returns the value of attribute scope.



38
39
40
# File 'lib/rhino/context.rb', line 38

def scope
  @scope
end

Class Method Details

.eval(javascript) ⇒ Object



48
49
50
# File 'lib/rhino/context.rb', line 48

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.



44
45
46
# File 'lib/rhino/context.rb', line 44

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

Instance Method Details

#[](k) ⇒ Object

Read a value from the global scope of this context



77
78
79
# File 'lib/rhino/context.rb', line 77

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

#[]=(k, v) ⇒ 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.



83
84
85
# File 'lib/rhino/context.rb', line 83

def []=(k, v)
  @scope[k] = v
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



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/rhino/context.rb', line 91

def eval(source, source_name = "<eval>", line_number = 1)
  self.open do
    begin
      scope = To.javascript(@scope)
      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
      To.ruby result
    rescue J::RhinoException => e
      raise Rhino::JavascriptError, e
    end
  end
end

#evaluate(*args) ⇒ Object

:nodoc:



107
108
109
# File 'lib/rhino/context.rb', line 107

def evaluate(*args) # :nodoc:
  self.eval(*args)
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



127
128
129
130
# File 'lib/rhino/context.rb', line 127

def instruction_limit=(limit)
  @native.setInstructionObserverThreshold(limit);
  @native.factory.instruction_limit = limit
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



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

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

#openObject

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



142
143
144
145
146
147
148
149
# File 'lib/rhino/context.rb', line 142

def open
  begin
    @native.factory.enterContext(@native)
    yield self
  ensure
    J::Context.exit()
  end if block_given?
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.



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

def optimization_level=(level)
  @native.setOptimizationLevel(level)
end