runtime.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. package otto
  2. import (
  3. "encoding"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "math"
  8. "path"
  9. "reflect"
  10. goruntime "runtime"
  11. "strconv"
  12. "strings"
  13. "sync"
  14. "github.com/robertkrimen/otto/ast"
  15. "github.com/robertkrimen/otto/parser"
  16. )
  17. type global struct {
  18. Object *object // Object( ... ), new Object( ... ) - 1 (length)
  19. Function *object // Function( ... ), new Function( ... ) - 1
  20. Array *object // Array( ... ), new Array( ... ) - 1
  21. String *object // String( ... ), new String( ... ) - 1
  22. Boolean *object // Boolean( ... ), new Boolean( ... ) - 1
  23. Number *object // Number( ... ), new Number( ... ) - 1
  24. Math *object
  25. Date *object // Date( ... ), new Date( ... ) - 7
  26. RegExp *object // RegExp( ... ), new RegExp( ... ) - 2
  27. Error *object // Error( ... ), new Error( ... ) - 1
  28. EvalError *object
  29. TypeError *object
  30. RangeError *object
  31. ReferenceError *object
  32. SyntaxError *object
  33. URIError *object
  34. JSON *object
  35. ObjectPrototype *object // Object.prototype
  36. FunctionPrototype *object // Function.prototype
  37. ArrayPrototype *object // Array.prototype
  38. StringPrototype *object // String.prototype
  39. BooleanPrototype *object // Boolean.prototype
  40. NumberPrototype *object // Number.prototype
  41. DatePrototype *object // Date.prototype
  42. RegExpPrototype *object // RegExp.prototype
  43. ErrorPrototype *object // Error.prototype
  44. EvalErrorPrototype *object
  45. TypeErrorPrototype *object
  46. RangeErrorPrototype *object
  47. ReferenceErrorPrototype *object
  48. SyntaxErrorPrototype *object
  49. URIErrorPrototype *object
  50. }
  51. type runtime struct {
  52. global global
  53. globalObject *object
  54. globalStash *objectStash
  55. scope *scope
  56. otto *Otto
  57. eval *object
  58. debugger func(*Otto)
  59. random func() float64
  60. labels []string
  61. stackLimit int
  62. traceLimit int
  63. lck sync.Mutex
  64. }
  65. func (rt *runtime) enterScope(scop *scope) {
  66. scop.outer = rt.scope
  67. if rt.scope != nil {
  68. if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit {
  69. panic(rt.panicRangeError("Maximum call stack size exceeded"))
  70. }
  71. scop.depth = rt.scope.depth + 1
  72. }
  73. rt.scope = scop
  74. }
  75. func (rt *runtime) leaveScope() {
  76. rt.scope = rt.scope.outer
  77. }
  78. // FIXME This is used in two places (cloning).
  79. func (rt *runtime) enterGlobalScope() {
  80. rt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject))
  81. }
  82. func (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash {
  83. if outer == nil {
  84. outer = rt.globalStash
  85. }
  86. stash := rt.newFunctionStash(outer)
  87. var thisObject *object
  88. switch this.kind {
  89. case valueUndefined, valueNull:
  90. thisObject = rt.globalObject
  91. default:
  92. thisObject = rt.toObject(this)
  93. }
  94. rt.enterScope(newScope(stash, stash, thisObject))
  95. return stash
  96. }
  97. func (rt *runtime) putValue(reference referencer, value Value) {
  98. name := reference.putValue(value)
  99. if name != "" {
  100. // Why? -- If reference.base == nil
  101. // strict = false
  102. rt.globalObject.defineProperty(name, value, 0o111, false)
  103. }
  104. }
  105. func (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint:nonamedreturns
  106. // resultValue = The value of the block (e.g. the last statement)
  107. // throw = Something was thrown
  108. // throwValue = The value of what was thrown
  109. // other = Something that changes flow (return, break, continue) that is not a throw
  110. // Otherwise, some sort of unknown panic happened, we'll just propagate it.
  111. defer func() {
  112. if caught := recover(); caught != nil {
  113. if excep, ok := caught.(*exception); ok {
  114. caught = excep.eject()
  115. }
  116. switch caught := caught.(type) {
  117. case ottoError:
  118. isException = true
  119. tryValue = objectValue(rt.newErrorObjectError(caught))
  120. case Value:
  121. isException = true
  122. tryValue = caught
  123. default:
  124. isException = true
  125. tryValue = toValue(caught)
  126. }
  127. }
  128. }()
  129. return inner(), false
  130. }
  131. func (rt *runtime) toObject(value Value) *object {
  132. switch value.kind {
  133. case valueEmpty, valueUndefined, valueNull:
  134. panic(rt.panicTypeError("toObject unsupported kind %s", value.kind))
  135. case valueBoolean:
  136. return rt.newBoolean(value)
  137. case valueString:
  138. return rt.newString(value)
  139. case valueNumber:
  140. return rt.newNumber(value)
  141. case valueObject:
  142. return value.object()
  143. default:
  144. panic(rt.panicTypeError("toObject unknown kind %s", value.kind))
  145. }
  146. }
  147. func (rt *runtime) objectCoerce(value Value) (*object, error) {
  148. switch value.kind {
  149. case valueUndefined:
  150. return nil, errors.New("undefined")
  151. case valueNull:
  152. return nil, errors.New("null")
  153. case valueBoolean:
  154. return rt.newBoolean(value), nil
  155. case valueString:
  156. return rt.newString(value), nil
  157. case valueNumber:
  158. return rt.newNumber(value), nil
  159. case valueObject:
  160. return value.object(), nil
  161. default:
  162. panic(rt.panicTypeError("objectCoerce unknown kind %s", value.kind))
  163. }
  164. }
  165. func checkObjectCoercible(rt *runtime, value Value) {
  166. isObject, mustCoerce := testObjectCoercible(value)
  167. if !isObject && !mustCoerce {
  168. panic(rt.panicTypeError("checkObjectCoercible not object or mustCoerce"))
  169. }
  170. }
  171. // testObjectCoercible.
  172. func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint:nonamedreturns
  173. switch value.kind {
  174. case valueReference, valueEmpty, valueNull, valueUndefined:
  175. return false, false
  176. case valueNumber, valueString, valueBoolean:
  177. return false, true
  178. case valueObject:
  179. return true, false
  180. default:
  181. panic(fmt.Sprintf("testObjectCoercible unknown kind %s", value.kind))
  182. }
  183. }
  184. func (rt *runtime) safeToValue(value interface{}) (Value, error) {
  185. result := Value{}
  186. err := catchPanic(func() {
  187. result = rt.toValue(value)
  188. })
  189. return result, err
  190. }
  191. // convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics.
  192. // This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily.
  193. func (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {
  194. val := reflect.ValueOf(v.export())
  195. if val.Kind() == t.Kind() {
  196. return val
  197. }
  198. if val.Kind() == reflect.Interface {
  199. val = reflect.ValueOf(val.Interface())
  200. }
  201. switch val.Kind() {
  202. case reflect.Float32, reflect.Float64:
  203. f64 := val.Float()
  204. switch t.Kind() {
  205. case reflect.Float64:
  206. return reflect.ValueOf(f64)
  207. case reflect.Float32:
  208. if reflect.Zero(t).OverflowFloat(f64) {
  209. panic(rt.panicRangeError("converting float64 to float32 would overflow"))
  210. }
  211. return val.Convert(t)
  212. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  213. i64 := int64(f64)
  214. if float64(i64) != f64 {
  215. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t)))
  216. }
  217. // The float represents an integer
  218. val = reflect.ValueOf(i64)
  219. default:
  220. panic(rt.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t)))
  221. }
  222. }
  223. switch val.Kind() {
  224. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  225. i64 := val.Int()
  226. switch t.Kind() {
  227. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  228. if reflect.Zero(t).OverflowInt(i64) {
  229. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
  230. }
  231. return val.Convert(t)
  232. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  233. if i64 < 0 {
  234. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t)))
  235. }
  236. if reflect.Zero(t).OverflowUint(uint64(i64)) {
  237. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
  238. }
  239. return val.Convert(t)
  240. case reflect.Float32, reflect.Float64:
  241. return val.Convert(t)
  242. }
  243. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  244. u64 := val.Uint()
  245. switch t.Kind() {
  246. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  247. if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) {
  248. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
  249. }
  250. return val.Convert(t)
  251. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  252. if reflect.Zero(t).OverflowUint(u64) {
  253. panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t)))
  254. }
  255. return val.Convert(t)
  256. case reflect.Float32, reflect.Float64:
  257. return val.Convert(t)
  258. }
  259. }
  260. panic(rt.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t)))
  261. }
  262. func fieldIndexByName(t reflect.Type, name string) []int {
  263. for t.Kind() == reflect.Ptr {
  264. t = t.Elem()
  265. }
  266. for i := range t.NumField() {
  267. f := t.Field(i)
  268. if !validGoStructName(f.Name) {
  269. continue
  270. }
  271. if f.Anonymous {
  272. for t.Kind() == reflect.Ptr {
  273. t = t.Elem()
  274. }
  275. if f.Type.Kind() == reflect.Struct {
  276. if a := fieldIndexByName(f.Type, name); a != nil {
  277. return append([]int{i}, a...)
  278. }
  279. }
  280. }
  281. if a := strings.SplitN(f.Tag.Get("json"), ",", 2); a[0] != "" {
  282. if a[0] == "-" {
  283. continue
  284. }
  285. if a[0] == name {
  286. return []int{i}
  287. }
  288. }
  289. if f.Name == name {
  290. return []int{i}
  291. }
  292. }
  293. return nil
  294. }
  295. var (
  296. typeOfValue = reflect.TypeOf(Value{})
  297. typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})
  298. )
  299. // convertCallParameter converts request val to type t if possible.
  300. // If the conversion fails due to overflow or type miss-match then it panics.
  301. // If no conversion is known then the original value is returned.
  302. func (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) {
  303. if t == typeOfValue {
  304. return reflect.ValueOf(v), nil
  305. }
  306. if t == typeOfJSONRawMessage {
  307. if d, err := json.Marshal(v.export()); err == nil {
  308. return reflect.ValueOf(d), nil
  309. }
  310. }
  311. if v.kind == valueObject {
  312. if gso, ok := v.object().value.(*goStructObject); ok {
  313. if gso.value.Type().AssignableTo(t) {
  314. // please see TestDynamicFunctionReturningInterface for why this exists
  315. if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) {
  316. return gso.value.Convert(t), nil
  317. }
  318. return gso.value, nil
  319. }
  320. }
  321. if gao, ok := v.object().value.(*goArrayObject); ok {
  322. if gao.value.Type().AssignableTo(t) {
  323. // please see TestDynamicFunctionReturningInterface for why this exists
  324. if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) {
  325. return gao.value.Convert(t), nil
  326. }
  327. return gao.value, nil
  328. }
  329. }
  330. }
  331. tk := t.Kind()
  332. if tk == reflect.Interface {
  333. e := v.export()
  334. if e == nil {
  335. return reflect.Zero(t), nil
  336. }
  337. iv := reflect.ValueOf(e)
  338. if iv.Type().AssignableTo(t) {
  339. return iv, nil
  340. }
  341. }
  342. if tk == reflect.Ptr {
  343. switch v.kind {
  344. case valueEmpty, valueNull, valueUndefined:
  345. return reflect.Zero(t), nil
  346. default:
  347. var vv reflect.Value
  348. vv, err := rt.convertCallParameter(v, t.Elem())
  349. if err != nil {
  350. return reflect.Zero(t), fmt.Errorf("can't convert to %s: %w", t, err)
  351. }
  352. if vv.CanAddr() {
  353. return vv.Addr(), nil
  354. }
  355. pv := reflect.New(vv.Type())
  356. pv.Elem().Set(vv)
  357. return pv, nil
  358. }
  359. }
  360. switch tk {
  361. case reflect.Bool:
  362. return reflect.ValueOf(v.bool()), nil
  363. case reflect.String:
  364. switch v.kind {
  365. case valueString:
  366. return reflect.ValueOf(v.value), nil
  367. case valueNumber:
  368. return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil
  369. }
  370. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
  371. if v.kind == valueNumber {
  372. return rt.convertNumeric(v, t), nil
  373. }
  374. case reflect.Slice:
  375. if o := v.object(); o != nil {
  376. if lv := o.get(propertyLength); lv.IsNumber() {
  377. l := lv.number().int64
  378. s := reflect.MakeSlice(t, int(l), int(l))
  379. tt := t.Elem()
  380. switch o.class {
  381. case classArrayName:
  382. for i := range l {
  383. p, ok := o.property[strconv.FormatInt(i, 10)]
  384. if !ok {
  385. continue
  386. }
  387. e, ok := p.value.(Value)
  388. if !ok {
  389. continue
  390. }
  391. ev, err := rt.convertCallParameter(e, tt)
  392. if err != nil {
  393. return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err)
  394. }
  395. s.Index(int(i)).Set(ev)
  396. }
  397. case classGoArrayName, classGoSliceName:
  398. var gslice bool
  399. switch o.value.(type) {
  400. case *goSliceObject:
  401. gslice = true
  402. case *goArrayObject:
  403. gslice = false
  404. }
  405. for i := range l {
  406. var p *property
  407. if gslice {
  408. p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10))
  409. } else {
  410. p = goArrayGetOwnProperty(o, strconv.FormatInt(i, 10))
  411. }
  412. if p == nil {
  413. continue
  414. }
  415. e, ok := p.value.(Value)
  416. if !ok {
  417. continue
  418. }
  419. ev, err := rt.convertCallParameter(e, tt)
  420. if err != nil {
  421. return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err)
  422. }
  423. s.Index(int(i)).Set(ev)
  424. }
  425. }
  426. return s, nil
  427. }
  428. }
  429. case reflect.Map:
  430. if o := v.object(); o != nil && t.Key().Kind() == reflect.String {
  431. m := reflect.MakeMap(t)
  432. var err error
  433. o.enumerate(false, func(k string) bool {
  434. v, verr := rt.convertCallParameter(o.get(k), t.Elem())
  435. if verr != nil {
  436. err = fmt.Errorf("couldn't convert property %q of %s: %w", k, t, verr)
  437. return false
  438. }
  439. m.SetMapIndex(reflect.ValueOf(k), v)
  440. return true
  441. })
  442. if err != nil {
  443. return reflect.Zero(t), err
  444. }
  445. return m, nil
  446. }
  447. case reflect.Func:
  448. if t.NumOut() > 1 {
  449. return reflect.Zero(t), errors.New("converting JavaScript values to Go functions with more than one return value is currently not supported")
  450. }
  451. if o := v.object(); o != nil && o.class == classFunctionName {
  452. return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {
  453. l := make([]interface{}, len(args))
  454. for i, a := range args {
  455. if a.CanInterface() {
  456. l[i] = a.Interface()
  457. }
  458. }
  459. rv, err := v.Call(nullValue, l...)
  460. if err != nil {
  461. panic(err)
  462. }
  463. if t.NumOut() == 0 {
  464. return nil
  465. }
  466. r, err := rt.convertCallParameter(rv, t.Out(0))
  467. if err != nil {
  468. panic(rt.panicTypeError("convertCallParameter Func: %s", err))
  469. }
  470. return []reflect.Value{r}
  471. }), nil
  472. }
  473. case reflect.Struct:
  474. if o := v.object(); o != nil && o.class == classObjectName {
  475. s := reflect.New(t)
  476. for _, k := range o.propertyOrder {
  477. idx := fieldIndexByName(t, k)
  478. if idx == nil {
  479. return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: field does not exist", k, t)
  480. }
  481. ss := s
  482. for _, i := range idx {
  483. if ss.Kind() == reflect.Ptr {
  484. if ss.IsNil() {
  485. if !ss.CanSet() {
  486. return reflect.Zero(t), fmt.Errorf("can't convert property %q of %s: %s is unexported", k, t, ss.Type().Elem())
  487. }
  488. ss.Set(reflect.New(ss.Type().Elem()))
  489. }
  490. ss = ss.Elem()
  491. }
  492. ss = ss.Field(i)
  493. }
  494. v, err := rt.convertCallParameter(o.get(k), ss.Type())
  495. if err != nil {
  496. return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %w", k, t, err)
  497. }
  498. ss.Set(v)
  499. }
  500. return s.Elem(), nil
  501. }
  502. }
  503. if tk == reflect.String {
  504. if o := v.object(); o != nil && o.hasProperty("toString") {
  505. if fn := o.get("toString"); fn.IsFunction() {
  506. sv, err := fn.Call(v)
  507. if err != nil {
  508. return reflect.Zero(t), fmt.Errorf("couldn't call toString: %w", err)
  509. }
  510. r, err := rt.convertCallParameter(sv, t)
  511. if err != nil {
  512. return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %w", err)
  513. }
  514. return r, nil
  515. }
  516. }
  517. return reflect.ValueOf(v.String()), nil
  518. }
  519. if v.kind == valueString {
  520. var s encoding.TextUnmarshaler
  521. if reflect.PointerTo(t).Implements(reflect.TypeOf(&s).Elem()) {
  522. r := reflect.New(t)
  523. if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil {
  524. return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %w", t.String(), err)
  525. }
  526. return r.Elem(), nil
  527. }
  528. }
  529. s := "OTTO DOES NOT UNDERSTAND THIS TYPE"
  530. switch v.kind {
  531. case valueBoolean:
  532. s = "boolean"
  533. case valueNull:
  534. s = "null"
  535. case valueNumber:
  536. s = "number"
  537. case valueString:
  538. s = "string"
  539. case valueUndefined:
  540. s = "undefined"
  541. case valueObject:
  542. s = v.Class()
  543. }
  544. return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t)
  545. }
  546. func (rt *runtime) toValue(value interface{}) Value {
  547. rv, ok := value.(reflect.Value)
  548. if ok {
  549. value = rv.Interface()
  550. }
  551. switch value := value.(type) {
  552. case Value:
  553. return value
  554. case func(FunctionCall) Value:
  555. var name, file string
  556. var line int
  557. pc := reflect.ValueOf(value).Pointer()
  558. fn := goruntime.FuncForPC(pc)
  559. if fn != nil {
  560. name = fn.Name()
  561. file, line = fn.FileLine(pc)
  562. file = path.Base(file)
  563. }
  564. return objectValue(rt.newNativeFunction(name, file, line, value))
  565. case nativeFunction:
  566. var name, file string
  567. var line int
  568. pc := reflect.ValueOf(value).Pointer()
  569. fn := goruntime.FuncForPC(pc)
  570. if fn != nil {
  571. name = fn.Name()
  572. file, line = fn.FileLine(pc)
  573. file = path.Base(file)
  574. }
  575. return objectValue(rt.newNativeFunction(name, file, line, value))
  576. case Object, *Object, object, *object:
  577. // Nothing happens.
  578. // FIXME We should really figure out what can come here.
  579. // This catch-all is ugly.
  580. default:
  581. val := reflect.ValueOf(value)
  582. if ok && val.Kind() == rv.Kind() {
  583. // Use passed in rv which may be writable.
  584. val = rv
  585. }
  586. switch val.Kind() {
  587. case reflect.Ptr:
  588. switch reflect.Indirect(val).Kind() {
  589. case reflect.Struct:
  590. return objectValue(rt.newGoStructObject(val))
  591. case reflect.Array:
  592. return objectValue(rt.newGoArray(val))
  593. }
  594. case reflect.Struct:
  595. return objectValue(rt.newGoStructObject(val))
  596. case reflect.Map:
  597. return objectValue(rt.newGoMapObject(val))
  598. case reflect.Slice:
  599. return objectValue(rt.newGoSlice(val))
  600. case reflect.Array:
  601. return objectValue(rt.newGoArray(val))
  602. case reflect.Func:
  603. var name, file string
  604. var line int
  605. if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr {
  606. pc := v.Pointer()
  607. fn := goruntime.FuncForPC(pc)
  608. if fn != nil {
  609. name = fn.Name()
  610. file, line = fn.FileLine(pc)
  611. file = path.Base(file)
  612. }
  613. }
  614. typ := val.Type()
  615. return objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value {
  616. nargs := typ.NumIn()
  617. if len(c.ArgumentList) != nargs {
  618. if typ.IsVariadic() {
  619. if len(c.ArgumentList) < nargs-1 {
  620. panic(rt.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList))))
  621. }
  622. } else {
  623. panic(rt.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList))))
  624. }
  625. }
  626. in := make([]reflect.Value, len(c.ArgumentList))
  627. callSlice := false
  628. for i, a := range c.ArgumentList {
  629. var t reflect.Type
  630. n := i
  631. if n >= nargs-1 && typ.IsVariadic() {
  632. if n > nargs-1 {
  633. n = nargs - 1
  634. }
  635. t = typ.In(n).Elem()
  636. } else {
  637. t = typ.In(n)
  638. }
  639. // if this is a variadic Go function, and the caller has supplied
  640. // exactly the number of JavaScript arguments required, and this
  641. // is the last JavaScript argument, try treating the it as the
  642. // actual set of variadic Go arguments. if that succeeds, break
  643. // out of the loop.
  644. if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 {
  645. if v, err := rt.convertCallParameter(a, typ.In(n)); err == nil {
  646. in[i] = v
  647. callSlice = true
  648. break
  649. }
  650. }
  651. v, err := rt.convertCallParameter(a, t)
  652. if err != nil {
  653. panic(rt.panicTypeError(err.Error()))
  654. }
  655. in[i] = v
  656. }
  657. var out []reflect.Value
  658. if callSlice {
  659. out = val.CallSlice(in)
  660. } else {
  661. out = val.Call(in)
  662. }
  663. switch len(out) {
  664. case 0:
  665. return Value{}
  666. case 1:
  667. return rt.toValue(out[0].Interface())
  668. default:
  669. s := make([]interface{}, len(out))
  670. for i, v := range out {
  671. s[i] = rt.toValue(v.Interface())
  672. }
  673. return rt.toValue(s)
  674. }
  675. }))
  676. }
  677. }
  678. return toValue(value)
  679. }
  680. func (rt *runtime) newGoSlice(value reflect.Value) *object {
  681. obj := rt.newGoSliceObject(value)
  682. obj.prototype = rt.global.ArrayPrototype
  683. return obj
  684. }
  685. func (rt *runtime) newGoArray(value reflect.Value) *object {
  686. obj := rt.newGoArrayObject(value)
  687. obj.prototype = rt.global.ArrayPrototype
  688. return obj
  689. }
  690. func (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) {
  691. return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
  692. }
  693. func (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) {
  694. program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)
  695. if err != nil {
  696. return nil, err
  697. }
  698. return cmplParse(program), nil
  699. }
  700. func (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) {
  701. switch src := src.(type) {
  702. case *ast.Program:
  703. return nil, src, nil
  704. case *Script:
  705. return src.program, nil, nil
  706. }
  707. program, err := rt.parse("", src, sm)
  708. return nil, program, err
  709. }
  710. func (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) {
  711. result := Value{}
  712. node, program, err := rt.parseSource(src, sm)
  713. if err != nil {
  714. return result, err
  715. }
  716. if node == nil {
  717. node = cmplParse(program)
  718. }
  719. err = catchPanic(func() {
  720. result = rt.cmplEvaluateNodeProgram(node, eval)
  721. })
  722. switch result.kind {
  723. case valueEmpty:
  724. result = Value{}
  725. case valueReference:
  726. result = result.resolve()
  727. }
  728. return result, err
  729. }
  730. func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) {
  731. return rt.cmplRunOrEval(src, sm, false)
  732. }
  733. func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) {
  734. return rt.cmplRunOrEval(src, sm, true)
  735. }
  736. func (rt *runtime) parseThrow(err error) {
  737. if err == nil {
  738. return
  739. }
  740. var errl parser.ErrorList
  741. if errors.Is(err, &errl) {
  742. err := errl[0]
  743. if err.Message == "invalid left-hand side in assignment" {
  744. panic(rt.panicReferenceError(err.Message))
  745. }
  746. panic(rt.panicSyntaxError(err.Message))
  747. }
  748. panic(rt.panicSyntaxError(err.Error()))
  749. }
  750. func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram {
  751. program, err := rt.cmplParse("", src, sm)
  752. rt.parseThrow(err) // Will panic/throw appropriately
  753. return program
  754. }