Class: V8::Context

Inherits:
Object
  • Object
show all
Includes:
Error::Try
Defined in:
lib/v8/context.rb

Overview

All JavaScript must be executed in a context. This context consists of a global scope containing the standard JavaScript objects¨and functions like Object, String, Array, as well as any objects or functions from Ruby which have been embedded into it from the containing enviroment. E.g.

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

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.new do |cxt|
  cxt['num'] = 5
  cxt.eval('num') # => 5
  Context.new do |cxt|
    cxt['num'] = 10
    cxt.eval('num') # => 10
    cxt.eval('++num') # => 11
  end
  cxt.eval('num') # => 5
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Error::Try

#try

Constructor Details

#initialize(options = {}) {|V8::Context| ... } ⇒ Context

Creates a new context.

If passed the `:with` option, that object will be used as the global scope of the newly creating context. e.g.

scope = Object.new
def scope.hello; "Hi"; end
V8::Context.new(:with => scope) do |cxt|
  cxt['hello'] #=> 'Hi'
end

If passed the `:timeout` option, every eval will timeout once

N milliseconds elapse

Parameters:

  • options (Hash<Symbol, Object>) (defaults to: {})

    initial context configuration

    • :with scope serves as the global scope of the new context

Yields:



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/v8/context.rb', line 64

def initialize(options = {})
  @conversion = Conversion.new
  @access = Access.new
  @timeout = options[:timeout]
  if global = options[:with]
    Context.new.enter do
      global_template = global.class.to_template.InstanceTemplate()
      @native = V8::C::Context::New(nil, global_template)
    end
    enter {link global, @native.Global()}
  else
    V8::C::Locker() do
      @native = V8::C::Context::New()
    end
  end
  yield self if block_given?
end

Instance Attribute Details

#accessObject (readonly)

Returns the value of attribute access



37
38
39
# File 'lib/v8/context.rb', line 37

def access
  @access
end

#conversionObject (readonly)

Returns the value of attribute conversion



33
34
35
# File 'lib/v8/context.rb', line 33

def conversion
  @conversion
end

#nativeObject (readonly)

Returns the value of attribute native



41
42
43
# File 'lib/v8/context.rb', line 41

def native
  @native
end

#timeoutObject (readonly)

Returns the value of attribute timeout



45
46
47
# File 'lib/v8/context.rb', line 45

def timeout
  @timeout
end

Class Method Details

.currentV8::Context

Get the currently entered context.

Returns:

  • (V8::Context)

    currently entered context, nil if none entered.



220
221
222
# File 'lib/v8/context.rb', line 220

def self.current
  Thread.current[:v8_context]
end

.enterObject



135
136
137
# File 'lib/v8/context.rb', line 135

def self.enter
  fail "cannot enter a context which has already been disposed"
end

Links `ruby_object` and `v8_object` inside the currently entered context. This is an error if no context has been entered.

Parameters:

  • ruby_object (Object)

    the Ruby half of the object identity

  • v8_object (V8::C::Object)

    the V8 half of the object identity.



190
191
192
# File 'lib/v8/context.rb', line 190

def self.link(ruby_object, v8_object)
  current.link ruby_object, v8_object
end

Instance Method Details

#[](key) ⇒ Object

Read a value from the global scope of this context

Parameters:

  • key (Object)

    the name of the value to read

Returns:

  • (Object)

    value the value at `key`



108
109
110
111
112
# File 'lib/v8/context.rb', line 108

def [](key)
  enter do
    to_ruby(@native.Global().Get(to_v8(key)))
  end
end

#[]=(key, value) ⇒ Object

Binds `value` to the name `key` in the global scope of this context.

Parameters:

  • key (Object)

    the name to bind to

  • value (Object)

    the value to bind



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

def []=(key, value)
  enter do
    @native.Global().Set(to_v8(key), to_v8(value))
  end
  return value
end

#disposeObject

Destroy this context and release any internal references it may contain to embedded Ruby objects.

A disposed context may never again be used for anything, and all objects created with it will become unusable.



130
131
132
133
134
135
136
137
138
# File 'lib/v8/context.rb', line 130

def dispose
  return unless @native
  @native.Dispose()
  @native = nil
  V8::C::V8::ContextDisposedNotification()
  def self.enter
    fail "cannot enter a context which has already been disposed"
  end
end

#enter(&block) ⇒ Object

Run some Ruby code in the context of this context.

This will acquire the V8 interpreter lock (possibly blocking until it is available), and prepare V8 for JavaScript execution.

Only one context may be running at a time per thread.

Returns:

  • (Object)

    the result of executing `block`



202
203
204
205
206
207
208
# File 'lib/v8/context.rb', line 202

def enter(&block)
  if !entered?
    lock_scope_and_enter(&block)
  else
    yield
  end
end

#entered?Boolean

Indicates if this context is the currently entered context

Returns:

  • (Boolean)

    true if this context is currently entered



213
214
215
# File 'lib/v8/context.rb', line 213

def entered?
  Context.current == self
end

#eval(source, filename = '<eval>', line = 1) ⇒ Object

Compile and execute a string of JavaScript source.

If `source` is an IO object it will be read fully before being evaluated

Parameters:

  • source (String, IO)

    the source code to compile and execute

  • filename (String) (defaults to: '<eval>')

    the name to use for this code when generating stack traces

  • line (Integer) (defaults to: 1)

    the line number to start with

Returns:

  • (Object)

    the result of the evaluation



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/v8/context.rb', line 90

def eval(source, filename = '<eval>', line = 1)
  if IO === source || StringIO === source
    source = source.read
  end
  enter do
    script = try { V8::C::Script::New(source.to_s, filename.to_s) }
    if @timeout
      to_ruby try {script.RunWithTimeout(@timeout)}
    else
      to_ruby try {script.Run()}
    end
  end
end

Marks a Ruby object and a v8 C++ Object as being the same. In other words whenever `ruby_object` is passed to v8, the result of the conversion should be `v8_object`. Conversely, whenever `v8_object` is passed to Ruby, the result of the conversion should be `ruby_object`. The Ruby Racer uses this mechanism to maintain referential integrity between Ruby and JavaScript peers

Parameters:

  • ruby_object (Object)

    the Ruby half of the object identity

  • v8_object (V8::C::Object)

    the V8 half of the object identity.

See Also:



181
182
183
# File 'lib/v8/context.rb', line 181

def link(ruby_object, v8_object)
  @conversion.equate ruby_object, v8_object
end

#load(filename) ⇒ Object

Compile and execute the contents of the file with path `filename` as JavaScript code.

Parameters:

  • filename (String)

    path to the file to execute.

Returns:

  • (Object)

    the result of the evaluation.



229
230
231
232
233
# File 'lib/v8/context.rb', line 229

def load(filename)
  File.open(filename) do |file|
    self.eval file, filename
  end
end

#scopeObject

Returns this context's global object. This will be a `V8::Object` if no scope was provided or just an `Object` if a Ruby object is serving as the global scope.

Returns:

  • (Object)

    scope the context's global scope.



145
146
147
# File 'lib/v8/context.rb', line 145

def scope
  enter { to_ruby @native.Global() }
end

#to_ruby(v8_object) ⇒ Object

Converts a v8 C++ object into its ruby counterpart. This is method is used to translate all values passed to Ruby from JavaScript, either as return values or as callback parameters.

Parameters:

  • v8_object (V8::C::Object)

    the native c++ object to convert.

Returns:

  • (Object)

    to pass to Ruby

See Also:



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

def to_ruby(v8_object)
  @conversion.to_ruby(v8_object)
end

#to_v8(ruby_object) ⇒ V8::C::Object

Converts a Ruby object into a native v8 C++ object. This method is used to translate all values passed to JavaScript from Ruby, either as return value or as callback parameters.

Parameters:

  • ruby_object (Object)

    the Ruby object to convert

Returns:

  • (V8::C::Object)

    to pass to V8

See Also:



167
168
169
# File 'lib/v8/context.rb', line 167

def to_v8(ruby_object)
  @conversion.to_v8(ruby_object)
end