object_goreflect.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. package goja
  2. import (
  3. "fmt"
  4. "go/ast"
  5. "reflect"
  6. "strings"
  7. "github.com/dop251/goja/parser"
  8. "github.com/dop251/goja/unistring"
  9. )
  10. // JsonEncodable allows custom JSON encoding by JSON.stringify()
  11. // Note that if the returned value itself also implements JsonEncodable, it won't have any effect.
  12. type JsonEncodable interface {
  13. JsonEncodable() interface{}
  14. }
  15. // FieldNameMapper provides custom mapping between Go and JavaScript property names.
  16. type FieldNameMapper interface {
  17. // FieldName returns a JavaScript name for the given struct field in the given type.
  18. // If this method returns "" the field becomes hidden.
  19. FieldName(t reflect.Type, f reflect.StructField) string
  20. // MethodName returns a JavaScript name for the given method in the given type.
  21. // If this method returns "" the method becomes hidden.
  22. MethodName(t reflect.Type, m reflect.Method) string
  23. }
  24. type tagFieldNameMapper struct {
  25. tagName string
  26. uncapMethods bool
  27. }
  28. func (tfm tagFieldNameMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
  29. tag := f.Tag.Get(tfm.tagName)
  30. if idx := strings.IndexByte(tag, ','); idx != -1 {
  31. tag = tag[:idx]
  32. }
  33. if parser.IsIdentifier(tag) {
  34. return tag
  35. }
  36. return ""
  37. }
  38. func uncapitalize(s string) string {
  39. return strings.ToLower(s[0:1]) + s[1:]
  40. }
  41. func (tfm tagFieldNameMapper) MethodName(_ reflect.Type, m reflect.Method) string {
  42. if tfm.uncapMethods {
  43. return uncapitalize(m.Name)
  44. }
  45. return m.Name
  46. }
  47. type uncapFieldNameMapper struct {
  48. }
  49. func (u uncapFieldNameMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
  50. return uncapitalize(f.Name)
  51. }
  52. func (u uncapFieldNameMapper) MethodName(_ reflect.Type, m reflect.Method) string {
  53. return uncapitalize(m.Name)
  54. }
  55. type reflectFieldInfo struct {
  56. Index []int
  57. Anonymous bool
  58. }
  59. type reflectFieldsInfo struct {
  60. Fields map[string]reflectFieldInfo
  61. Names []string
  62. }
  63. type reflectMethodsInfo struct {
  64. Methods map[string]int
  65. Names []string
  66. }
  67. type reflectValueWrapper interface {
  68. esValue() Value
  69. reflectValue() reflect.Value
  70. setReflectValue(reflect.Value)
  71. }
  72. func isContainer(k reflect.Kind) bool {
  73. switch k {
  74. case reflect.Struct, reflect.Slice, reflect.Array:
  75. return true
  76. }
  77. return false
  78. }
  79. func copyReflectValueWrapper(w reflectValueWrapper) {
  80. v := w.reflectValue()
  81. c := reflect.New(v.Type()).Elem()
  82. c.Set(v)
  83. w.setReflectValue(c)
  84. }
  85. type objectGoReflect struct {
  86. baseObject
  87. origValue, fieldsValue reflect.Value
  88. fieldsInfo *reflectFieldsInfo
  89. methodsInfo *reflectMethodsInfo
  90. methodsValue reflect.Value
  91. valueCache map[string]reflectValueWrapper
  92. toString, valueOf func() Value
  93. toJson func() interface{}
  94. }
  95. func (o *objectGoReflect) init() {
  96. o.baseObject.init()
  97. switch o.fieldsValue.Kind() {
  98. case reflect.Bool:
  99. o.class = classBoolean
  100. o.prototype = o.val.runtime.global.BooleanPrototype
  101. o.toString = o._toStringBool
  102. o.valueOf = o._valueOfBool
  103. case reflect.String:
  104. o.class = classString
  105. o.prototype = o.val.runtime.global.StringPrototype
  106. o.toString = o._toStringString
  107. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  108. o.class = classNumber
  109. o.prototype = o.val.runtime.global.NumberPrototype
  110. o.valueOf = o._valueOfInt
  111. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  112. o.class = classNumber
  113. o.prototype = o.val.runtime.global.NumberPrototype
  114. o.valueOf = o._valueOfUint
  115. case reflect.Float32, reflect.Float64:
  116. o.class = classNumber
  117. o.prototype = o.val.runtime.global.NumberPrototype
  118. o.valueOf = o._valueOfFloat
  119. default:
  120. o.class = classObject
  121. o.prototype = o.val.runtime.global.ObjectPrototype
  122. }
  123. if o.fieldsValue.Kind() == reflect.Struct {
  124. o.fieldsInfo = o.val.runtime.fieldsInfo(o.fieldsValue.Type())
  125. }
  126. var methodsType reflect.Type
  127. // Always use pointer type for non-interface values to be able to access both methods defined on
  128. // the literal type and on the pointer.
  129. if o.fieldsValue.Kind() != reflect.Interface {
  130. methodsType = reflect.PtrTo(o.fieldsValue.Type())
  131. } else {
  132. methodsType = o.fieldsValue.Type()
  133. }
  134. o.methodsInfo = o.val.runtime.methodsInfo(methodsType)
  135. // Container values and values that have at least one method defined on the pointer type
  136. // need to be addressable.
  137. if !o.origValue.CanAddr() && (isContainer(o.origValue.Kind()) || len(o.methodsInfo.Names) > 0) {
  138. value := reflect.New(o.origValue.Type()).Elem()
  139. value.Set(o.origValue)
  140. o.origValue = value
  141. if value.Kind() != reflect.Ptr {
  142. o.fieldsValue = value
  143. }
  144. }
  145. o.extensible = true
  146. switch o.origValue.Interface().(type) {
  147. case fmt.Stringer:
  148. o.toString = o._toStringStringer
  149. case error:
  150. o.toString = o._toStringError
  151. }
  152. if o.toString != nil || o.valueOf != nil {
  153. o.baseObject._putProp("toString", o.val.runtime.newNativeFunc(o.toStringFunc, nil, "toString", nil, 0), true, false, true)
  154. o.baseObject._putProp("valueOf", o.val.runtime.newNativeFunc(o.valueOfFunc, nil, "valueOf", nil, 0), true, false, true)
  155. }
  156. if len(o.methodsInfo.Names) > 0 && o.fieldsValue.Kind() != reflect.Interface {
  157. o.methodsValue = o.fieldsValue.Addr()
  158. } else {
  159. o.methodsValue = o.fieldsValue
  160. }
  161. if j, ok := o.origValue.Interface().(JsonEncodable); ok {
  162. o.toJson = j.JsonEncodable
  163. }
  164. }
  165. func (o *objectGoReflect) toStringFunc(FunctionCall) Value {
  166. return o.toPrimitiveString()
  167. }
  168. func (o *objectGoReflect) valueOfFunc(FunctionCall) Value {
  169. return o.toPrimitiveNumber()
  170. }
  171. func (o *objectGoReflect) getStr(name unistring.String, receiver Value) Value {
  172. if v := o._get(name.String()); v != nil {
  173. return v
  174. }
  175. return o.baseObject.getStr(name, receiver)
  176. }
  177. func (o *objectGoReflect) _getField(jsName string) reflect.Value {
  178. if o.fieldsInfo != nil {
  179. if info, exists := o.fieldsInfo.Fields[jsName]; exists {
  180. return o.fieldsValue.FieldByIndex(info.Index)
  181. }
  182. }
  183. return reflect.Value{}
  184. }
  185. func (o *objectGoReflect) _getMethod(jsName string) reflect.Value {
  186. if o.methodsInfo != nil {
  187. if idx, exists := o.methodsInfo.Methods[jsName]; exists {
  188. return o.methodsValue.Method(idx)
  189. }
  190. }
  191. return reflect.Value{}
  192. }
  193. func (o *objectGoReflect) elemToValue(ev reflect.Value) (Value, reflectValueWrapper) {
  194. if isContainer(ev.Kind()) {
  195. ret := o.val.runtime.toValue(ev.Interface(), ev)
  196. if obj, ok := ret.(*Object); ok {
  197. if w, ok := obj.self.(reflectValueWrapper); ok {
  198. return ret, w
  199. }
  200. }
  201. return ret, nil
  202. }
  203. if ev.Kind() == reflect.Interface {
  204. ev = ev.Elem()
  205. }
  206. if ev.Kind() == reflect.Invalid {
  207. return _null, nil
  208. }
  209. return o.val.runtime.toValue(ev.Interface(), ev), nil
  210. }
  211. func (o *objectGoReflect) _getFieldValue(name string) Value {
  212. if v := o.valueCache[name]; v != nil {
  213. return v.esValue()
  214. }
  215. if v := o._getField(name); v.IsValid() {
  216. res, w := o.elemToValue(v)
  217. if w != nil {
  218. if o.valueCache == nil {
  219. o.valueCache = make(map[string]reflectValueWrapper)
  220. }
  221. o.valueCache[name] = w
  222. }
  223. return res
  224. }
  225. return nil
  226. }
  227. func (o *objectGoReflect) _get(name string) Value {
  228. if o.fieldsValue.Kind() == reflect.Struct {
  229. if ret := o._getFieldValue(name); ret != nil {
  230. return ret
  231. }
  232. }
  233. if v := o._getMethod(name); v.IsValid() {
  234. return o.val.runtime.toValue(v.Interface(), v)
  235. }
  236. return nil
  237. }
  238. func (o *objectGoReflect) getOwnPropStr(name unistring.String) Value {
  239. n := name.String()
  240. if o.fieldsValue.Kind() == reflect.Struct {
  241. if v := o._getFieldValue(n); v != nil {
  242. return &valueProperty{
  243. value: v,
  244. writable: true,
  245. enumerable: true,
  246. }
  247. }
  248. }
  249. if v := o._getMethod(n); v.IsValid() {
  250. return &valueProperty{
  251. value: o.val.runtime.toValue(v.Interface(), v),
  252. enumerable: true,
  253. }
  254. }
  255. return nil
  256. }
  257. func (o *objectGoReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
  258. has, ok := o._put(name.String(), val, throw)
  259. if !has {
  260. if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
  261. o.val.runtime.typeErrorResult(throw, "Cannot assign to property %s of a host object", name)
  262. return false
  263. } else {
  264. return res
  265. }
  266. }
  267. return ok
  268. }
  269. func (o *objectGoReflect) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  270. return o._setForeignStr(name, trueValIfPresent(o._has(name.String())), val, receiver, throw)
  271. }
  272. func (o *objectGoReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
  273. return o._setForeignIdx(idx, nil, val, receiver, throw)
  274. }
  275. func (o *objectGoReflect) _put(name string, val Value, throw bool) (has, ok bool) {
  276. if o.fieldsValue.Kind() == reflect.Struct {
  277. if v := o._getField(name); v.IsValid() {
  278. cached := o.valueCache[name]
  279. if cached != nil {
  280. copyReflectValueWrapper(cached)
  281. }
  282. err := o.val.runtime.toReflectValue(val, v, &objectExportCtx{})
  283. if err != nil {
  284. if cached != nil {
  285. cached.setReflectValue(v)
  286. }
  287. o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err)
  288. return true, false
  289. }
  290. if cached != nil {
  291. delete(o.valueCache, name)
  292. }
  293. return true, true
  294. }
  295. }
  296. return false, false
  297. }
  298. func (o *objectGoReflect) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value {
  299. if _, ok := o._put(name.String(), value, false); ok {
  300. return value
  301. }
  302. return o.baseObject._putProp(name, value, writable, enumerable, configurable)
  303. }
  304. func (r *Runtime) checkHostObjectPropertyDescr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  305. if descr.Getter != nil || descr.Setter != nil {
  306. r.typeErrorResult(throw, "Host objects do not support accessor properties")
  307. return false
  308. }
  309. if descr.Writable == FLAG_FALSE {
  310. r.typeErrorResult(throw, "Host object field %s cannot be made read-only", name)
  311. return false
  312. }
  313. if descr.Configurable == FLAG_TRUE {
  314. r.typeErrorResult(throw, "Host object field %s cannot be made configurable", name)
  315. return false
  316. }
  317. return true
  318. }
  319. func (o *objectGoReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  320. if o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
  321. n := name.String()
  322. if has, ok := o._put(n, descr.Value, throw); !has {
  323. o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a host object", n)
  324. return false
  325. } else {
  326. return ok
  327. }
  328. }
  329. return false
  330. }
  331. func (o *objectGoReflect) _has(name string) bool {
  332. if o.fieldsValue.Kind() == reflect.Struct {
  333. if v := o._getField(name); v.IsValid() {
  334. return true
  335. }
  336. }
  337. if v := o._getMethod(name); v.IsValid() {
  338. return true
  339. }
  340. return false
  341. }
  342. func (o *objectGoReflect) hasOwnPropertyStr(name unistring.String) bool {
  343. return o._has(name.String())
  344. }
  345. func (o *objectGoReflect) _valueOfInt() Value {
  346. return intToValue(o.fieldsValue.Int())
  347. }
  348. func (o *objectGoReflect) _valueOfUint() Value {
  349. return intToValue(int64(o.fieldsValue.Uint()))
  350. }
  351. func (o *objectGoReflect) _valueOfBool() Value {
  352. if o.fieldsValue.Bool() {
  353. return valueTrue
  354. } else {
  355. return valueFalse
  356. }
  357. }
  358. func (o *objectGoReflect) _valueOfFloat() Value {
  359. return floatToValue(o.fieldsValue.Float())
  360. }
  361. func (o *objectGoReflect) _toStringStringer() Value {
  362. return newStringValue(o.origValue.Interface().(fmt.Stringer).String())
  363. }
  364. func (o *objectGoReflect) _toStringString() Value {
  365. return newStringValue(o.fieldsValue.String())
  366. }
  367. func (o *objectGoReflect) _toStringBool() Value {
  368. if o.fieldsValue.Bool() {
  369. return stringTrue
  370. } else {
  371. return stringFalse
  372. }
  373. }
  374. func (o *objectGoReflect) _toStringError() Value {
  375. return newStringValue(o.origValue.Interface().(error).Error())
  376. }
  377. func (o *objectGoReflect) toPrimitiveNumber() Value {
  378. if o.valueOf != nil {
  379. return o.valueOf()
  380. }
  381. if o.toString != nil {
  382. return o.toString()
  383. }
  384. return o.baseObject.toPrimitiveNumber()
  385. }
  386. func (o *objectGoReflect) toPrimitiveString() Value {
  387. if o.toString != nil {
  388. return o.toString()
  389. }
  390. if o.valueOf != nil {
  391. return o.valueOf().toString()
  392. }
  393. return o.baseObject.toPrimitiveString()
  394. }
  395. func (o *objectGoReflect) toPrimitive() Value {
  396. if o.valueOf != nil {
  397. return o.valueOf()
  398. }
  399. if o.toString != nil {
  400. return o.toString()
  401. }
  402. return o.baseObject.toPrimitive()
  403. }
  404. func (o *objectGoReflect) deleteStr(name unistring.String, throw bool) bool {
  405. n := name.String()
  406. if o._has(n) {
  407. o.val.runtime.typeErrorResult(throw, "Cannot delete property %s from a Go type", n)
  408. return false
  409. }
  410. return o.baseObject.deleteStr(name, throw)
  411. }
  412. type goreflectPropIter struct {
  413. o *objectGoReflect
  414. idx int
  415. }
  416. func (i *goreflectPropIter) nextField() (propIterItem, iterNextFunc) {
  417. names := i.o.fieldsInfo.Names
  418. if i.idx < len(names) {
  419. name := names[i.idx]
  420. i.idx++
  421. return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.nextField
  422. }
  423. i.idx = 0
  424. return i.nextMethod()
  425. }
  426. func (i *goreflectPropIter) nextMethod() (propIterItem, iterNextFunc) {
  427. names := i.o.methodsInfo.Names
  428. if i.idx < len(names) {
  429. name := names[i.idx]
  430. i.idx++
  431. return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.nextMethod
  432. }
  433. return propIterItem{}, nil
  434. }
  435. func (o *objectGoReflect) iterateStringKeys() iterNextFunc {
  436. r := &goreflectPropIter{
  437. o: o,
  438. }
  439. if o.fieldsInfo != nil {
  440. return r.nextField
  441. }
  442. return r.nextMethod
  443. }
  444. func (o *objectGoReflect) stringKeys(_ bool, accum []Value) []Value {
  445. // all own keys are enumerable
  446. if o.fieldsInfo != nil {
  447. for _, name := range o.fieldsInfo.Names {
  448. accum = append(accum, newStringValue(name))
  449. }
  450. }
  451. for _, name := range o.methodsInfo.Names {
  452. accum = append(accum, newStringValue(name))
  453. }
  454. return accum
  455. }
  456. func (o *objectGoReflect) export(*objectExportCtx) interface{} {
  457. return o.origValue.Interface()
  458. }
  459. func (o *objectGoReflect) exportType() reflect.Type {
  460. return o.origValue.Type()
  461. }
  462. func (o *objectGoReflect) equal(other objectImpl) bool {
  463. if other, ok := other.(*objectGoReflect); ok {
  464. k1, k2 := o.fieldsValue.Kind(), other.fieldsValue.Kind()
  465. if k1 == k2 {
  466. if isContainer(k1) {
  467. return o.fieldsValue == other.fieldsValue
  468. }
  469. return o.fieldsValue.Interface() == other.fieldsValue.Interface()
  470. }
  471. }
  472. return false
  473. }
  474. func (o *objectGoReflect) reflectValue() reflect.Value {
  475. return o.fieldsValue
  476. }
  477. func (o *objectGoReflect) setReflectValue(v reflect.Value) {
  478. o.fieldsValue = v
  479. o.origValue = v
  480. o.methodsValue = v.Addr()
  481. }
  482. func (o *objectGoReflect) esValue() Value {
  483. return o.val
  484. }
  485. func (r *Runtime) buildFieldInfo(t reflect.Type, index []int, info *reflectFieldsInfo) {
  486. n := t.NumField()
  487. for i := 0; i < n; i++ {
  488. field := t.Field(i)
  489. name := field.Name
  490. if !ast.IsExported(name) {
  491. continue
  492. }
  493. if r.fieldNameMapper != nil {
  494. name = r.fieldNameMapper.FieldName(t, field)
  495. }
  496. if name != "" {
  497. if inf, exists := info.Fields[name]; !exists {
  498. info.Names = append(info.Names, name)
  499. } else {
  500. if len(inf.Index) <= len(index) {
  501. continue
  502. }
  503. }
  504. }
  505. if name != "" || field.Anonymous {
  506. idx := make([]int, len(index)+1)
  507. copy(idx, index)
  508. idx[len(idx)-1] = i
  509. if name != "" {
  510. info.Fields[name] = reflectFieldInfo{
  511. Index: idx,
  512. Anonymous: field.Anonymous,
  513. }
  514. }
  515. if field.Anonymous {
  516. typ := field.Type
  517. for typ.Kind() == reflect.Ptr {
  518. typ = typ.Elem()
  519. }
  520. if typ.Kind() == reflect.Struct {
  521. r.buildFieldInfo(typ, idx, info)
  522. }
  523. }
  524. }
  525. }
  526. }
  527. var emptyMethodsInfo = reflectMethodsInfo{}
  528. func (r *Runtime) buildMethodsInfo(t reflect.Type) (info *reflectMethodsInfo) {
  529. n := t.NumMethod()
  530. if n == 0 {
  531. return &emptyMethodsInfo
  532. }
  533. info = new(reflectMethodsInfo)
  534. info.Methods = make(map[string]int, n)
  535. info.Names = make([]string, 0, n)
  536. for i := 0; i < n; i++ {
  537. method := t.Method(i)
  538. name := method.Name
  539. if !ast.IsExported(name) {
  540. continue
  541. }
  542. if r.fieldNameMapper != nil {
  543. name = r.fieldNameMapper.MethodName(t, method)
  544. if name == "" {
  545. continue
  546. }
  547. }
  548. if _, exists := info.Methods[name]; !exists {
  549. info.Names = append(info.Names, name)
  550. }
  551. info.Methods[name] = i
  552. }
  553. return
  554. }
  555. func (r *Runtime) buildFieldsInfo(t reflect.Type) (info *reflectFieldsInfo) {
  556. info = new(reflectFieldsInfo)
  557. n := t.NumField()
  558. info.Fields = make(map[string]reflectFieldInfo, n)
  559. info.Names = make([]string, 0, n)
  560. r.buildFieldInfo(t, nil, info)
  561. return
  562. }
  563. func (r *Runtime) fieldsInfo(t reflect.Type) (info *reflectFieldsInfo) {
  564. var exists bool
  565. if info, exists = r.fieldsInfoCache[t]; !exists {
  566. info = r.buildFieldsInfo(t)
  567. if r.fieldsInfoCache == nil {
  568. r.fieldsInfoCache = make(map[reflect.Type]*reflectFieldsInfo)
  569. }
  570. r.fieldsInfoCache[t] = info
  571. }
  572. return
  573. }
  574. func (r *Runtime) methodsInfo(t reflect.Type) (info *reflectMethodsInfo) {
  575. var exists bool
  576. if info, exists = r.methodsInfoCache[t]; !exists {
  577. info = r.buildMethodsInfo(t)
  578. if r.methodsInfoCache == nil {
  579. r.methodsInfoCache = make(map[reflect.Type]*reflectMethodsInfo)
  580. }
  581. r.methodsInfoCache[t] = info
  582. }
  583. return
  584. }
  585. // SetFieldNameMapper sets a custom field name mapper for Go types. It can be called at any time, however
  586. // the mapping for any given value is fixed at the point of creation.
  587. // Setting this to nil restores the default behaviour which is all exported fields and methods are mapped to their
  588. // original unchanged names.
  589. func (r *Runtime) SetFieldNameMapper(mapper FieldNameMapper) {
  590. r.fieldNameMapper = mapper
  591. r.fieldsInfoCache = nil
  592. r.methodsInfoCache = nil
  593. }
  594. // TagFieldNameMapper returns a FieldNameMapper that uses the given tagName for struct fields and optionally
  595. // uncapitalises (making the first letter lower case) method names.
  596. // The common tag value syntax is supported (name[,options]), however options are ignored.
  597. // Setting name to anything other than a valid ECMAScript identifier makes the field hidden.
  598. func TagFieldNameMapper(tagName string, uncapMethods bool) FieldNameMapper {
  599. return tagFieldNameMapper{
  600. tagName: tagName,
  601. uncapMethods: uncapMethods,
  602. }
  603. }
  604. // UncapFieldNameMapper returns a FieldNameMapper that uncapitalises struct field and method names
  605. // making the first letter lower case.
  606. func UncapFieldNameMapper() FieldNameMapper {
  607. return uncapFieldNameMapper{}
  608. }