aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/robertkrimen/otto/type_array.go
blob: 236376a8e430a7411ad3bfd5f348bb3c4e7e2d9c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package otto

import (
    "strconv"
)

func (runtime *_runtime) newArrayObject(length uint32) *_object {
    self := runtime.newObject()
    self.class = "Array"
    self.defineProperty("length", toValue_uint32(length), 0100, false)
    self.objectClass = _classArray
    return self
}

func isArray(object *_object) bool {
    return object != nil && (object.class == "Array" || object.class == "GoArray")
}

func objectLength(object *_object) uint32 {
    if object == nil {
        return 0
    }
    switch object.class {
    case "Array":
        return object.get("length").value.(uint32)
    case "String":
        return uint32(object.get("length").value.(int))
    case "GoArray":
        return uint32(object.get("length").value.(int))
    }
    return 0
}

func arrayUint32(rt *_runtime, value Value) uint32 {
    nm := value.number()
    if nm.kind != numberInteger || !isUint32(nm.int64) {
        // FIXME
        panic(rt.panicRangeError())
    }
    return uint32(nm.int64)
}

func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
    lengthProperty := self.getOwnProperty("length")
    lengthValue, valid := lengthProperty.value.(Value)
    if !valid {
        panic("Array.length != Value{}")
    }
    length := lengthValue.value.(uint32)
    if name == "length" {
        if descriptor.value == nil {
            return objectDefineOwnProperty(self, name, descriptor, throw)
        }
        newLengthValue, isValue := descriptor.value.(Value)
        if !isValue {
            panic(self.runtime.panicTypeError())
        }
        newLength := arrayUint32(self.runtime, newLengthValue)
        descriptor.value = toValue_uint32(newLength)
        if newLength > length {
            return objectDefineOwnProperty(self, name, descriptor, throw)
        }
        if !lengthProperty.writable() {
            goto Reject
        }
        newWritable := true
        if descriptor.mode&0700 == 0 {
            // If writable is off
            newWritable = false
            descriptor.mode |= 0100
        }
        if !objectDefineOwnProperty(self, name, descriptor, throw) {
            return false
        }
        for newLength < length {
            length -= 1
            if !self.delete(strconv.FormatInt(int64(length), 10), false) {
                descriptor.value = toValue_uint32(length + 1)
                if !newWritable {
                    descriptor.mode &= 0077
                }
                objectDefineOwnProperty(self, name, descriptor, false)
                goto Reject
            }
        }
        if !newWritable {
            descriptor.mode &= 0077
            objectDefineOwnProperty(self, name, descriptor, false)
        }
    } else if index := stringToArrayIndex(name); index >= 0 {
        if index >= int64(length) && !lengthProperty.writable() {
            goto Reject
        }
        if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) {
            goto Reject
        }
        if index >= int64(length) {
            lengthProperty.value = toValue_uint32(uint32(index + 1))
            objectDefineOwnProperty(self, "length", *lengthProperty, false)
            return true
        }
    }
    return objectDefineOwnProperty(self, name, descriptor, throw)
Reject:
    if throw {
        panic(self.runtime.panicTypeError())
    }
    return false
}