mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
153 lines
4.1 KiB
Ruby
153 lines
4.1 KiB
Ruby
module V8
|
|
class Portal
|
|
class Interceptors
|
|
def initialize(portal)
|
|
@portal
|
|
@getter = NamedPropertyGetter.new(portal)
|
|
@setter = NamedPropertySetter.new(portal)
|
|
@query = nil
|
|
@deleter = nil
|
|
@enumerator = NamedPropertyEnumerator.new(portal)
|
|
@igetter = IndexedPropertyGetter.new(portal)
|
|
@isetter = IndexedPropertySetter.new(portal)
|
|
@iquery = nil
|
|
@ideleter = nil
|
|
@ienumerator = IndexedPropertyEnumerator.new(portal)
|
|
end
|
|
|
|
def setup(template)
|
|
template.SetNamedPropertyHandler(@getter,@setter,@query,@deleter,@enumerator)
|
|
template.SetIndexedPropertyHandler(@igetter,@isetter,@iquery,@ideleter,@ienumerator)
|
|
end
|
|
|
|
class PropertyAttributes
|
|
attr_reader :flags
|
|
def initialize
|
|
@flags = 0
|
|
end
|
|
|
|
def read_only
|
|
tap do
|
|
@flags |= V8::C::ReadOnly
|
|
end
|
|
end
|
|
|
|
def dont_enum
|
|
tap do
|
|
@flags |= V8::C::DontEnum
|
|
end
|
|
end
|
|
|
|
def dont_delete
|
|
tap do
|
|
@flags |= V8::C::DontDelete
|
|
end
|
|
end
|
|
end
|
|
|
|
class Interceptor
|
|
|
|
def initialize(portal)
|
|
@to, @access = portal, portal.access
|
|
end
|
|
|
|
def intercept(info, retval = nil, &code)
|
|
obj = @to.rb(info.This())
|
|
intercepts = true
|
|
result = @to.rubyprotect do
|
|
dontintercept = proc do
|
|
intercepts = false
|
|
end
|
|
code.call(obj, dontintercept)
|
|
end
|
|
intercepts ? (retval || result) : C::Empty
|
|
end
|
|
end
|
|
|
|
class NamedPropertyGetter < Interceptor
|
|
def call(property, info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.get(obj, @to.rb(property), &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class NamedPropertySetter < Interceptor
|
|
def call(property, value, info)
|
|
intercept(info, value) do |obj, dontintercept|
|
|
@access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class NamedPropertyQuery
|
|
def call(property, info)
|
|
attributes = PropertyAttributes.new
|
|
result = intercept(info) do |obj, dontintercept|
|
|
@access.query(obj, @to.rb(property), attributes, &dontintercept)
|
|
end
|
|
return result == C::Empty ? result : C::Integer::New(attributes.flags)
|
|
end
|
|
end
|
|
|
|
class NamedPropertyEnumerator < Interceptor
|
|
def call(info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.names(obj, &dontintercept).to_a
|
|
end
|
|
end
|
|
end
|
|
|
|
class NamedPropertyDeleter < Interceptor
|
|
def call(property, info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.delete(obj, property, &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class IndexedPropertyGetter < Interceptor
|
|
def call(index, info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.iget(obj, index, &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class IndexedPropertySetter < Interceptor
|
|
def call(index, value, info)
|
|
intercept(info, value) do |obj, dontintercept|
|
|
@access.iset(obj, index, @to.rb(value), &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class IndexedPropertyQuery < Interceptor
|
|
def call(property, info)
|
|
attributes = PropertyAttributes.new
|
|
result = intercept(info) do |obj, dontintercept|
|
|
@access.indices(obj, &dontintercept)
|
|
end
|
|
result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
|
|
end
|
|
end
|
|
|
|
class IndexedPropertyDeleter < Interceptor
|
|
def call(index, info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.idelete(obj, index, &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
|
|
class IndexedPropertyEnumerator < Interceptor
|
|
def call(info)
|
|
intercept(info) do |obj, dontintercept|
|
|
@access.indices(obj, &dontintercept)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|