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.



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

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

#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

#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



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

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

Instance Method Details

#can_put(prop) ⇒ Object



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

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

#construct(opts = {}) ⇒ Object



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

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
  @constructing = false
end

#constructing?Boolean

Returns:



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

def constructing?
  @constructing
end

#default_value(hint = nil) ⇒ Object



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
169
# File 'lib/twostroke/runtime/types/object.rb', line 137

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



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

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



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

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



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

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



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

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



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

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



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

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



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

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



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

def get_property(prop)
  # @TODO?
end

#has_accessor(prop) ⇒ Object



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

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

#has_own_property(prop) ⇒ Object



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

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

#has_property(prop) ⇒ Object



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

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



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

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

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



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

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



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

def typeof
  "object"
end