1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00
therubyracer/lib/v8/portal/interceptors.rb

154 lines
4.1 KiB
Ruby
Raw Normal View History

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