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:



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

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.



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

def access
  @access
end

#conversionObject (readonly)

Returns the value of attribute conversion.



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

def conversion
  @conversion
end

#nativeObject (readonly)

Returns the value of attribute native.



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

def native
  @native
end

#timeoutObject (readonly)

maximum execution time for script in milliseconds



43
44
45
# File 'lib/v8/context.rb', line 43

def timeout
  @timeout
end

Class Method Details

.currentV8::Context

Get the currently entered context.

Returns:

  • (V8::Context)

    currently entered context, nil if none entered.



218
219
220
# File 'lib/v8/context.rb', line 218

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

.enterObject



133
134
135
# File 'lib/v8/context.rb', line 133

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.



188
189
190
# File 'lib/v8/context.rb', line 188

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`



106
107
108
109
110
# File 'lib/v8/context.rb', line 106

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



116
117
118
119
120
121
# File 'lib/v8/context.rb', line 116

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.



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

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`



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

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



211
212
213
# File 'lib/v8/context.rb', line 211

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



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

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:



179
180
181
# File 'lib/v8/context.rb', line 179

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.



227
228
229
230
231
# File 'lib/v8/context.rb', line 227

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.



143
144
145
# File 'lib/v8/context.rb', line 143

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:



154
155
156
# File 'lib/v8/context.rb', line 154

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:



165
166
167
# File 'lib/v8/context.rb', line 165

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