2024-02-24 21:00:04 +00:00
|
|
|
package otto
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
type object struct {
|
|
|
|
runtime *runtime
|
2024-02-24 21:00:04 +00:00
|
|
|
|
|
|
|
class string
|
2024-04-04 14:46:14 +00:00
|
|
|
objectClass *objectClass
|
2024-02-24 21:00:04 +00:00
|
|
|
value interface{}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
prototype *object
|
2024-02-24 21:00:04 +00:00
|
|
|
extensible bool
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
property map[string]property
|
2024-02-24 21:00:04 +00:00
|
|
|
propertyOrder []string
|
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func newObject(rt *runtime, class string) *object {
|
|
|
|
o := &object{
|
|
|
|
runtime: rt,
|
2024-02-24 21:00:04 +00:00
|
|
|
class: class,
|
2024-04-04 14:46:14 +00:00
|
|
|
objectClass: classObject,
|
|
|
|
property: make(map[string]property),
|
2024-02-24 21:00:04 +00:00
|
|
|
extensible: true,
|
|
|
|
}
|
2024-04-04 14:46:14 +00:00
|
|
|
return o
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 8.12
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.1.
|
|
|
|
func (o *object) getOwnProperty(name string) *property {
|
|
|
|
return o.objectClass.getOwnProperty(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.2.
|
|
|
|
func (o *object) getProperty(name string) *property {
|
|
|
|
return o.objectClass.getProperty(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.3.
|
|
|
|
func (o *object) get(name string) Value {
|
|
|
|
return o.objectClass.get(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.4.
|
|
|
|
func (o *object) canPut(name string) bool {
|
|
|
|
return o.objectClass.canPut(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.5.
|
|
|
|
func (o *object) put(name string, value Value, throw bool) {
|
|
|
|
o.objectClass.put(o, name, value, throw)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.6.
|
|
|
|
func (o *object) hasProperty(name string) bool {
|
|
|
|
return o.objectClass.hasProperty(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) hasOwnProperty(name string) bool {
|
|
|
|
return o.objectClass.hasOwnProperty(o, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
type defaultValueHint int
|
2024-02-24 21:00:04 +00:00
|
|
|
|
|
|
|
const (
|
2024-04-04 14:46:14 +00:00
|
|
|
defaultValueNoHint defaultValueHint = iota
|
2024-02-24 21:00:04 +00:00
|
|
|
defaultValueHintString
|
|
|
|
defaultValueHintNumber
|
|
|
|
)
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.8.
|
|
|
|
func (o *object) DefaultValue(hint defaultValueHint) Value {
|
2024-02-24 21:00:04 +00:00
|
|
|
if hint == defaultValueNoHint {
|
2024-04-04 14:46:14 +00:00
|
|
|
if o.class == classDateName {
|
2024-02-24 21:00:04 +00:00
|
|
|
// Date exception
|
|
|
|
hint = defaultValueHintString
|
|
|
|
} else {
|
|
|
|
hint = defaultValueHintNumber
|
|
|
|
}
|
|
|
|
}
|
|
|
|
methodSequence := []string{"valueOf", "toString"}
|
|
|
|
if hint == defaultValueHintString {
|
|
|
|
methodSequence = []string{"toString", "valueOf"}
|
|
|
|
}
|
|
|
|
for _, methodName := range methodSequence {
|
2024-04-04 14:46:14 +00:00
|
|
|
method := o.get(methodName)
|
2024-02-24 21:00:04 +00:00
|
|
|
// FIXME This is redundant...
|
|
|
|
if method.isCallable() {
|
2024-04-04 14:46:14 +00:00
|
|
|
result := method.object().call(objectValue(o), nil, false, nativeFrame)
|
2024-02-24 21:00:04 +00:00
|
|
|
if result.IsPrimitive() {
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
panic(o.runtime.panicTypeError("Object.DefaultValue unknown"))
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) String() string {
|
|
|
|
return o.DefaultValue(defaultValueHintString).string()
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint: unparam
|
|
|
|
return o.defineOwnProperty(name, property{value, mode}, throw)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
// 8.12.9.
|
|
|
|
func (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool {
|
|
|
|
return o.objectClass.defineOwnProperty(o, name, descriptor, throw)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) delete(name string, throw bool) bool {
|
|
|
|
return o.objectClass.delete(o, name, throw)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) enumerate(all bool, each func(string) bool) {
|
|
|
|
o.objectClass.enumerate(o, all, each)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) readProperty(name string) (property, bool) {
|
|
|
|
prop, exists := o.property[name]
|
|
|
|
return prop, exists
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) writeProperty(name string, value interface{}, mode propertyMode) {
|
2024-02-24 21:00:04 +00:00
|
|
|
if value == nil {
|
|
|
|
value = Value{}
|
|
|
|
}
|
2024-04-04 14:46:14 +00:00
|
|
|
if _, exists := o.property[name]; !exists {
|
|
|
|
o.propertyOrder = append(o.propertyOrder, name)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
2024-04-04 14:46:14 +00:00
|
|
|
o.property[name] = property{value, mode}
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
|
2024-04-04 14:46:14 +00:00
|
|
|
func (o *object) deleteProperty(name string) {
|
|
|
|
if _, exists := o.property[name]; !exists {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
delete(o.property, name)
|
|
|
|
for index, prop := range o.propertyOrder {
|
|
|
|
if name == prop {
|
|
|
|
if index == len(o.propertyOrder)-1 {
|
|
|
|
o.propertyOrder = o.propertyOrder[:index]
|
|
|
|
} else {
|
|
|
|
o.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...)
|
2024-02-24 21:00:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|