Class: Twostroke::Runtime::Types::Object

Inherits:
Value
  • Object
show all
Defined in:
lib/twostroke/runtime/types/object.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Value

#has_instance

Constructor Details

#initializeObject

Returns a new instance of Object.



6
7
8
9
10
11
12
13
14
# File 'lib/twostroke/runtime/types/object.rb', line 6

def initialize
  @extensible = true
  @properties = {}
  @accessors = {}
  @prototype ||= defined?(@@_prototype) ? @@_prototype : Null.new
  @_class = self.class.constructor_function if !defined?(@_class) && self.class.respond_to?(:constructor_function)
  @data = {} # for abitrary data not safe to store as a property
  proto_put "constructor", @_class
end

Instance Attribute Details

#_classObject

Returns the value of attribute _class.



3
4
5
# File 'lib/twostroke/runtime/types/object.rb', line 3

def _class
  @_class
end

#accessorsObject (readonly)

Returns the value of attribute accessors.



4
5
6
# File 'lib/twostroke/runtime/types/object.rb', line 4

def accessors
  @accessors
end

#dataObject (readonly)

Returns the value of attribute data.



4
5
6
# File 'lib/twostroke/runtime/types/object.rb', line 4

def data
  @data
end

#extensibleObject (readonly)

Returns the value of attribute extensible.



4
5
6
# File 'lib/twostroke/runtime/types/object.rb', line 4

def extensible
  @extensible
end

#propertiesObject (readonly)

Returns the value of attribute properties.



4
5
6
# File 'lib/twostroke/runtime/types/object.rb', line 4

def properties
  @properties
end

#prototypeObject

Returns the value of attribute prototype.



3
4
5
# File 'lib/twostroke/runtime/types/object.rb', line 3

def prototype
  @prototype
end

Class Method Details

.set_global_prototype(proto) ⇒ Object



20
21
22
# File 'lib/twostroke/runtime/types/object.rb', line 20

def self.set_global_prototype(proto)
  @@_prototype = proto
end

Instance Method Details

#can_put(prop) ⇒ Object



104
105
106
# File 'lib/twostroke/runtime/types/object.rb', line 104

def can_put(prop)
  extensible && (!accessors.has_key?(prop) || accessors[prop][:configurable])
end

#construct(opts = {}) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/twostroke/runtime/types/object.rb', line 42

def construct(opts = {})
  @constructing = true
  opts.each do |k,v|
    if respond_to? "#{k}="
      send "#{k}=", v
    else
      instance_variable_set "@#{k}", v
    end
  end
  yield if block_given?
  @constructing = false
end

#constructing?Boolean

Returns:



28
29
30
# File 'lib/twostroke/runtime/types/object.rb', line 28

def constructing?
  @constructing
end

#default_value(hint = nil) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/twostroke/runtime/types/object.rb', line 136

def default_value(hint = nil)      
  if hint.nil?
    # @TODO
    # hint = is_a?(Date) ? "String" : "Number"
    hint = "Number"
  end
  
  if hint == "String"
    toString = get "toString"
    if toString.respond_to? :call
      str = toString.call(nil, self, [])
      return str if str.is_a? Primitive
    end
    valueOf = get "valueOf"
    if valueOf.respond_to? :call
      val = valueOf.call(nil, self, [])
      return val if val.is_a? Primitive
    end
    Twostroke::Runtime::Lib.throw_type_error "could not convert object to string"
  elsif hint == "Number"
    valueOf = get "valueOf"
    if valueOf.respond_to? :call
      val = valueOf.call(nil, self, [])
      return val if val.is_a? Primitive
    end
    toString = get "toString"
    if toString.respond_to? :call
      str = toString.call(nil, self, [])
      return str if str.is_a? Primitive
    end
    Twostroke::Runtime::Lib.throw_type_error "could not convert object to string"
  end
end

#define_own_property(prop, descriptor) ⇒ Object



170
171
172
173
174
175
176
177
178
179
# File 'lib/twostroke/runtime/types/object.rb', line 170

def define_own_property(prop, descriptor)
  unless descriptor.has_key?(:get) || descriptor.has_key?(:set)
    descriptor[:get] = ->(this) { descriptor[:value] }
    descriptor[:set] = ->(this, value) { descriptor[:value] = value }
    descriptor[:value] ||= Undefined.new
  else
    descriptor[:writable] = true if descriptor.has_key?(:set)
  end
  accessors[prop] = descriptor
end

#delete(prop) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/twostroke/runtime/types/object.rb', line 120

def delete(prop)
  if accessors.has_key? prop
    accessors.delete prop if accessors[prop][:configurable]
  elsif prop != "prototype"
    properties.delete prop
  end
end

#delete!(prop) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/twostroke/runtime/types/object.rb', line 128

def delete!(prop)
  if accessors.has_key? prop
    accessors.delete prop if accessors[prop][:configurable]
  else
    properties.delete prop
  end
end

#each_enumerable_property(&bk) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/twostroke/runtime/types/object.rb', line 79

def each_enumerable_property(&bk)
  accessors.select { |k,v| v[:enumerable] }.each { |k,v| yield k }
  properties.reject { |k,v| accessors[k] }.each { |k,v| yield k }
  if prototype && prototype.is_a?(Object)
    prototype.each_enumerable_property &bk
  end
end

#generic_itemsObject

this allows us to treat the object like a generic array. the value of this method is not memoized, so call sparingly



34
35
36
37
38
39
40
# File 'lib/twostroke/runtime/types/object.rb', line 34

def generic_items
  return items if respond_to? :items
  len = Twostroke::Runtime::Types.to_number(get "length").number
  return [] if (len.is_a?(Float) && (len.nan? || len.infinite?)) || len < 0
  len = len.to_i
  (0...len).map { |i| get i.to_s }
end

#get(prop, this = self) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/twostroke/runtime/types/object.rb', line 55

def get(prop, this = self)
  if accessors.has_key? prop
    accessors[prop][:get].(this)
  elsif properties.has_key? prop
    properties[prop]
  else
    prototype && prototype.is_a?(Object) ? prototype.get(prop, this) : Undefined.new
  end
end

#get_own_property(prop) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/twostroke/runtime/types/object.rb', line 65

def get_own_property(prop)
  if accessors.has_key? prop
    accessors[prop][:get] ? accessors[prop][:get].(this) : Undefined.new
  elsif properties.has_key? prop
    properties[prop]
  else
    Undefined.new
  end
end

#get_property(prop) ⇒ Object



75
76
77
# File 'lib/twostroke/runtime/types/object.rb', line 75

def get_property(prop)
  # @TODO?
end

#has_accessor(prop) ⇒ Object



112
113
114
# File 'lib/twostroke/runtime/types/object.rb', line 112

def has_accessor(prop)
  accessors.has_key?(prop)
end

#has_own_property(prop) ⇒ Object



116
117
118
# File 'lib/twostroke/runtime/types/object.rb', line 116

def has_own_property(prop)
  accessors.has_key?(prop) || properties.has_key?(prop)
end

#has_property(prop) ⇒ Object



108
109
110
# File 'lib/twostroke/runtime/types/object.rb', line 108

def has_property(prop)
  accessors.has_key?(prop) || properties.has_key?(prop) || (prototype && prototype.is_a?(Object) && prototype.has_property(prop))
end

#proto_put(prop, value) ⇒ Object

puts prop as a non-enumerable property



100
101
102
# File 'lib/twostroke/runtime/types/object.rb', line 100

def proto_put(prop, value)
  define_own_property prop, value: value, enumerable: false
end

#put(prop, value, this = self) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/twostroke/runtime/types/object.rb', line 87

def put(prop, value, this = self)
  if accessors.has_key? prop
    accessors[prop][:set].(this, value) if accessors[prop][:set] && accessors[prop][:writable]
  elsif properties.has_key? prop
    properties[prop] = value
#      elsif prototype && prototype.is_a?(Object) && prototype.has_accessor(prop)
#        prototype.put prop, value, this
  else
    properties[prop] = value
  end
end

#typeofObject



24
25
26
# File 'lib/twostroke/runtime/types/object.rb', line 24

def typeof
  "object"
end