mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
Add documentation for Context class
This commit is contained in:
parent
8d1e348de0
commit
f45f006406
1 changed files with 132 additions and 9 deletions
|
@ -1,9 +1,56 @@
|
|||
require 'stringio'
|
||||
module V8
|
||||
# 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
|
||||
class Context
|
||||
include V8::Error::Try
|
||||
attr_reader :native, :conversion, :access
|
||||
|
||||
# defines conversion behavior for this context
|
||||
# @see V8::Conversion
|
||||
attr_reader :conversion
|
||||
|
||||
# defines access to Ruby objects for this context
|
||||
# @see V8::Access
|
||||
attr_reader :access
|
||||
|
||||
# a reference to the underlying C++ object
|
||||
attr_reader :native
|
||||
|
||||
# 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
|
||||
#
|
||||
# @param Hash options initial context configuration
|
||||
# * :with => Object scope serves as the global scope of the new context
|
||||
def initialize(options = {})
|
||||
@conversion = Conversion.new
|
||||
@access = Access.new
|
||||
|
@ -19,6 +66,14 @@ module V8
|
|||
yield self if block_given?
|
||||
end
|
||||
|
||||
# Compile and execute a string of JavaScript source.
|
||||
#
|
||||
# If `source` is an IO object it will be read fully before being evaluated
|
||||
#
|
||||
# @param Object source the source code to compile and execute
|
||||
# @param String filename the name to use for this code when generating stack traces
|
||||
# @param Integer line the line number to start with
|
||||
# @return Object the result of the evaluation
|
||||
def eval(source, filename = '<eval>', line = 1)
|
||||
if IO === source || StringIO === source
|
||||
source = source.read
|
||||
|
@ -29,12 +84,20 @@ module V8
|
|||
end
|
||||
end
|
||||
|
||||
# Read a value from the global scope of this context
|
||||
#
|
||||
# @param Object key the name of the value to read
|
||||
# @return Object value the value at `key`
|
||||
def [](key)
|
||||
enter do
|
||||
to_ruby(@native.Global().Get(to_v8(key)))
|
||||
end
|
||||
end
|
||||
|
||||
# Binds `value` to the name `key` in the global scope of this context.
|
||||
#
|
||||
# @param key the name to bind to
|
||||
# @param value the value to bind
|
||||
def []=(key, value)
|
||||
enter do
|
||||
@native.Global().Set(to_v8(key), to_v8(value))
|
||||
|
@ -42,6 +105,11 @@ module V8
|
|||
return value
|
||||
end
|
||||
|
||||
# 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.
|
||||
def dispose
|
||||
return unless @native
|
||||
@native.Dispose()
|
||||
|
@ -52,26 +120,68 @@ module V8
|
|||
end
|
||||
end
|
||||
|
||||
# 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.
|
||||
#
|
||||
# @return Object scope the context's global scope.
|
||||
def scope
|
||||
enter { to_ruby @native.Global() }
|
||||
end
|
||||
|
||||
# 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.
|
||||
#
|
||||
# @param V8::C::Object v8_object the native c++ object to convert.
|
||||
# @return Object to pass to Ruby
|
||||
# @see V8::Conversion for how to customize and extend this mechanism
|
||||
def to_ruby(v8_object)
|
||||
@conversion.to_ruby(v8_object)
|
||||
end
|
||||
|
||||
# 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.
|
||||
#
|
||||
# @param Object ruby_object the Ruby object to convert
|
||||
# @return V8::C::Object to pass to V8
|
||||
# @see V8::Conversion for customizing and extending this mechanism
|
||||
def to_v8(ruby_object)
|
||||
@conversion.to_v8(ruby_object)
|
||||
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
|
||||
#
|
||||
# @param Object ruby_object the Ruby half of the object identity
|
||||
# @param V8::C::Object v8_object the V8 half of the object identity.
|
||||
# @see V8::Conversion::Identity
|
||||
def link(ruby_object, v8_object)
|
||||
@conversion.equate ruby_object, v8_object
|
||||
end
|
||||
|
||||
def self.link(*args)
|
||||
current.link *args
|
||||
# Links `ruby_object` and `v8_object` inside the currently entered
|
||||
# context. This is an error if no context has been entered.
|
||||
#
|
||||
# @param Object ruby_object the Ruby half of the object identity
|
||||
# @param V8::C::Object v8_object the V8 half of the object identity.
|
||||
def self.link(ruby_object, v8_object)
|
||||
current.link ruby_object, v8_object
|
||||
end
|
||||
|
||||
# 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.
|
||||
#
|
||||
# @return Object the result of executing `block`
|
||||
def enter(&block)
|
||||
if !entered?
|
||||
lock_scope_and_enter(&block)
|
||||
|
@ -80,14 +190,33 @@ module V8
|
|||
end
|
||||
end
|
||||
|
||||
# Indicates if this context is the currently entered context
|
||||
#
|
||||
# @return true if this context is currently entered
|
||||
def entered?
|
||||
Context.current == self
|
||||
end
|
||||
|
||||
# Get the currently entered context.
|
||||
#
|
||||
# @return V8::Context currently entered context, nil if none entered.
|
||||
def self.current
|
||||
Thread.current[:v8_context]
|
||||
end
|
||||
|
||||
# Compile and execute the contents of the file with path `filename`
|
||||
# as JavaScript code.
|
||||
#
|
||||
# @param String filename path to the file to execute.
|
||||
# @return Object the result of the evaluation.
|
||||
def load(filename)
|
||||
File.open(filename) do |file|
|
||||
self.eval file, filename
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.current=(context)
|
||||
Thread.current[:v8_context] = context
|
||||
end
|
||||
|
@ -108,11 +237,5 @@ module V8
|
|||
ensure
|
||||
Context.current = current
|
||||
end
|
||||
|
||||
def load(filename)
|
||||
File.open(filename) do |file|
|
||||
self.eval file, filename
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue