global.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package otto
  2. import (
  3. "strconv"
  4. "time"
  5. )
  6. var (
  7. prototypeValueObject = interface{}(nil)
  8. prototypeValueFunction = _nativeFunctionObject{
  9. call: func(_ FunctionCall) Value {
  10. return Value{}
  11. },
  12. }
  13. prototypeValueString = _stringASCII("")
  14. // TODO Make this just false?
  15. prototypeValueBoolean = Value{
  16. kind: valueBoolean,
  17. value: false,
  18. }
  19. prototypeValueNumber = Value{
  20. kind: valueNumber,
  21. value: 0,
  22. }
  23. prototypeValueDate = _dateObject{
  24. epoch: 0,
  25. isNaN: false,
  26. time: time.Unix(0, 0).UTC(),
  27. value: Value{
  28. kind: valueNumber,
  29. value: 0,
  30. },
  31. }
  32. prototypeValueRegExp = _regExpObject{
  33. regularExpression: nil,
  34. global: false,
  35. ignoreCase: false,
  36. multiline: false,
  37. source: "",
  38. flags: "",
  39. }
  40. )
  41. func newContext() *_runtime {
  42. self := &_runtime{}
  43. self.globalStash = self.newObjectStash(nil, nil)
  44. self.globalObject = self.globalStash.object
  45. _newContext(self)
  46. self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object)
  47. self.globalObject.prototype = self.global.ObjectPrototype
  48. return self
  49. }
  50. func (runtime *_runtime) newBaseObject() *_object {
  51. self := newObject(runtime, "")
  52. return self
  53. }
  54. func (runtime *_runtime) newClassObject(class string) *_object {
  55. return newObject(runtime, class)
  56. }
  57. func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
  58. self := runtime.newClassObject(class)
  59. self.value = value
  60. return self
  61. }
  62. func (self *_object) primitiveValue() Value {
  63. switch value := self.value.(type) {
  64. case Value:
  65. return value
  66. case _stringObject:
  67. return toValue_string(value.String())
  68. }
  69. return Value{}
  70. }
  71. func (self *_object) hasPrimitive() bool {
  72. switch self.value.(type) {
  73. case Value, _stringObject:
  74. return true
  75. }
  76. return false
  77. }
  78. func (runtime *_runtime) newObject() *_object {
  79. self := runtime.newClassObject("Object")
  80. self.prototype = runtime.global.ObjectPrototype
  81. return self
  82. }
  83. func (runtime *_runtime) newArray(length uint32) *_object {
  84. self := runtime.newArrayObject(length)
  85. self.prototype = runtime.global.ArrayPrototype
  86. return self
  87. }
  88. func (runtime *_runtime) newArrayOf(valueArray []Value) *_object {
  89. self := runtime.newArray(uint32(len(valueArray)))
  90. for index, value := range valueArray {
  91. if value.isEmpty() {
  92. continue
  93. }
  94. self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false)
  95. }
  96. return self
  97. }
  98. func (runtime *_runtime) newString(value Value) *_object {
  99. self := runtime.newStringObject(value)
  100. self.prototype = runtime.global.StringPrototype
  101. return self
  102. }
  103. func (runtime *_runtime) newBoolean(value Value) *_object {
  104. self := runtime.newBooleanObject(value)
  105. self.prototype = runtime.global.BooleanPrototype
  106. return self
  107. }
  108. func (runtime *_runtime) newNumber(value Value) *_object {
  109. self := runtime.newNumberObject(value)
  110. self.prototype = runtime.global.NumberPrototype
  111. return self
  112. }
  113. func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object {
  114. pattern := ""
  115. flags := ""
  116. if object := patternValue._object(); object != nil && object.class == "RegExp" {
  117. if flagsValue.IsDefined() {
  118. panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another"))
  119. }
  120. regExp := object.regExpValue()
  121. pattern = regExp.source
  122. flags = regExp.flags
  123. } else {
  124. if patternValue.IsDefined() {
  125. pattern = patternValue.string()
  126. }
  127. if flagsValue.IsDefined() {
  128. flags = flagsValue.string()
  129. }
  130. }
  131. return runtime._newRegExp(pattern, flags)
  132. }
  133. func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object {
  134. self := runtime.newRegExpObject(pattern, flags)
  135. self.prototype = runtime.global.RegExpPrototype
  136. return self
  137. }
  138. // TODO Should (probably) be one argument, right? This is redundant
  139. func (runtime *_runtime) newDate(epoch float64) *_object {
  140. self := runtime.newDateObject(epoch)
  141. self.prototype = runtime.global.DatePrototype
  142. return self
  143. }
  144. func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object {
  145. var self *_object
  146. switch name {
  147. case "EvalError":
  148. return runtime.newEvalError(message)
  149. case "TypeError":
  150. return runtime.newTypeError(message)
  151. case "RangeError":
  152. return runtime.newRangeError(message)
  153. case "ReferenceError":
  154. return runtime.newReferenceError(message)
  155. case "SyntaxError":
  156. return runtime.newSyntaxError(message)
  157. case "URIError":
  158. return runtime.newURIError(message)
  159. }
  160. self = runtime.newErrorObject(name, message, stackFramesToPop)
  161. self.prototype = runtime.global.ErrorPrototype
  162. if name != "" {
  163. self.defineProperty("name", toValue_string(name), 0111, false)
  164. }
  165. return self
  166. }
  167. func (runtime *_runtime) newNativeFunction(name, file string, line int, _nativeFunction _nativeFunction) *_object {
  168. self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0)
  169. self.prototype = runtime.global.FunctionPrototype
  170. prototype := runtime.newObject()
  171. self.defineProperty("prototype", toValue_object(prototype), 0100, false)
  172. prototype.defineProperty("constructor", toValue_object(self), 0100, false)
  173. return self
  174. }
  175. func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object {
  176. // TODO Implement 13.2 fully
  177. self := runtime.newNodeFunctionObject(node, scopeEnvironment)
  178. self.prototype = runtime.global.FunctionPrototype
  179. prototype := runtime.newObject()
  180. self.defineProperty("prototype", toValue_object(prototype), 0100, false)
  181. prototype.defineProperty("constructor", toValue_object(self), 0101, false)
  182. return self
  183. }
  184. // FIXME Only in one place...
  185. func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object {
  186. self := runtime.newBoundFunctionObject(target, this, argumentList)
  187. self.prototype = runtime.global.FunctionPrototype
  188. prototype := runtime.newObject()
  189. self.defineProperty("prototype", toValue_object(prototype), 0100, false)
  190. prototype.defineProperty("constructor", toValue_object(self), 0100, false)
  191. return self
  192. }