File: type_array.go

package info (click to toggle)
golang-github-robertkrimen-otto 0.0~git20200922.ef014fd-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 1,796 kB
  • sloc: perl: 1,227; makefile: 79
file content (109 lines) | stat: -rw-r--r-- 2,863 bytes parent folder | download | duplicates (2)
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--
			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
}