compiler.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. package goja
  2. import (
  3. "fmt"
  4. "github.com/dop251/goja/token"
  5. "sort"
  6. "github.com/dop251/goja/ast"
  7. "github.com/dop251/goja/file"
  8. "github.com/dop251/goja/unistring"
  9. )
  10. type blockType int
  11. const (
  12. blockLoop blockType = iota
  13. blockLoopEnum
  14. blockTry
  15. blockLabel
  16. blockSwitch
  17. blockWith
  18. blockScope
  19. blockIterScope
  20. blockOptChain
  21. )
  22. const (
  23. maskConst = 1 << 31
  24. maskVar = 1 << 30
  25. maskDeletable = 1 << 29
  26. maskStrict = maskDeletable
  27. maskTyp = maskConst | maskVar | maskDeletable
  28. )
  29. type varType byte
  30. const (
  31. varTypeVar varType = iota
  32. varTypeLet
  33. varTypeStrictConst
  34. varTypeConst
  35. )
  36. const thisBindingName = " this" // must not be a valid identifier
  37. type CompilerError struct {
  38. Message string
  39. File *file.File
  40. Offset int
  41. }
  42. type CompilerSyntaxError struct {
  43. CompilerError
  44. }
  45. type CompilerReferenceError struct {
  46. CompilerError
  47. }
  48. type srcMapItem struct {
  49. pc int
  50. srcPos int
  51. }
  52. type Program struct {
  53. code []instruction
  54. values []Value
  55. funcName unistring.String
  56. src *file.File
  57. srcMap []srcMapItem
  58. }
  59. type compiler struct {
  60. p *Program
  61. scope *scope
  62. block *block
  63. classScope *classScope
  64. enumGetExpr compiledEnumGetExpr
  65. evalVM *vm // VM used to evaluate constant expressions
  66. ctxVM *vm // VM in which an eval() code is compiled
  67. codeScratchpad []instruction
  68. }
  69. type binding struct {
  70. scope *scope
  71. name unistring.String
  72. accessPoints map[*scope]*[]int
  73. isConst bool
  74. isStrict bool
  75. isArg bool
  76. isVar bool
  77. inStash bool
  78. }
  79. func (b *binding) getAccessPointsForScope(s *scope) *[]int {
  80. m := b.accessPoints[s]
  81. if m == nil {
  82. a := make([]int, 0, 1)
  83. m = &a
  84. if b.accessPoints == nil {
  85. b.accessPoints = make(map[*scope]*[]int)
  86. }
  87. b.accessPoints[s] = m
  88. }
  89. return m
  90. }
  91. func (b *binding) markAccessPointAt(pos int) {
  92. scope := b.scope.c.scope
  93. m := b.getAccessPointsForScope(scope)
  94. *m = append(*m, pos-scope.base)
  95. }
  96. func (b *binding) markAccessPointAtScope(scope *scope, pos int) {
  97. m := b.getAccessPointsForScope(scope)
  98. *m = append(*m, pos-scope.base)
  99. }
  100. func (b *binding) markAccessPoint() {
  101. scope := b.scope.c.scope
  102. m := b.getAccessPointsForScope(scope)
  103. *m = append(*m, len(scope.prg.code)-scope.base)
  104. }
  105. func (b *binding) emitGet() {
  106. b.markAccessPoint()
  107. if b.isVar && !b.isArg {
  108. b.scope.c.emit(loadStack(0))
  109. } else {
  110. b.scope.c.emit(loadStackLex(0))
  111. }
  112. }
  113. func (b *binding) emitGetAt(pos int) {
  114. b.markAccessPointAt(pos)
  115. if b.isVar && !b.isArg {
  116. b.scope.c.p.code[pos] = loadStack(0)
  117. } else {
  118. b.scope.c.p.code[pos] = loadStackLex(0)
  119. }
  120. }
  121. func (b *binding) emitGetP() {
  122. if b.isVar && !b.isArg {
  123. // no-op
  124. } else {
  125. // make sure TDZ is checked
  126. b.markAccessPoint()
  127. b.scope.c.emit(loadStackLex(0), pop)
  128. }
  129. }
  130. func (b *binding) emitSet() {
  131. if b.isConst {
  132. if b.isStrict || b.scope.c.scope.strict {
  133. b.scope.c.emit(throwAssignToConst)
  134. }
  135. return
  136. }
  137. b.markAccessPoint()
  138. if b.isVar && !b.isArg {
  139. b.scope.c.emit(storeStack(0))
  140. } else {
  141. b.scope.c.emit(storeStackLex(0))
  142. }
  143. }
  144. func (b *binding) emitSetP() {
  145. if b.isConst {
  146. if b.isStrict || b.scope.c.scope.strict {
  147. b.scope.c.emit(throwAssignToConst)
  148. }
  149. return
  150. }
  151. b.markAccessPoint()
  152. if b.isVar && !b.isArg {
  153. b.scope.c.emit(storeStackP(0))
  154. } else {
  155. b.scope.c.emit(storeStackLexP(0))
  156. }
  157. }
  158. func (b *binding) emitInitP() {
  159. if !b.isVar && b.scope.outer == nil {
  160. b.scope.c.emit(initGlobalP(b.name))
  161. } else {
  162. b.markAccessPoint()
  163. b.scope.c.emit(initStackP(0))
  164. }
  165. }
  166. func (b *binding) emitInit() {
  167. if !b.isVar && b.scope.outer == nil {
  168. b.scope.c.emit(initGlobal(b.name))
  169. } else {
  170. b.markAccessPoint()
  171. b.scope.c.emit(initStack(0))
  172. }
  173. }
  174. func (b *binding) emitInitAt(pos int) {
  175. if !b.isVar && b.scope.outer == nil {
  176. b.scope.c.p.code[pos] = initGlobal(b.name)
  177. } else {
  178. b.markAccessPointAt(pos)
  179. b.scope.c.p.code[pos] = initStack(0)
  180. }
  181. }
  182. func (b *binding) emitInitAtScope(scope *scope, pos int) {
  183. if !b.isVar && scope.outer == nil {
  184. scope.c.p.code[pos] = initGlobal(b.name)
  185. } else {
  186. b.markAccessPointAtScope(scope, pos)
  187. scope.c.p.code[pos] = initStack(0)
  188. }
  189. }
  190. func (b *binding) emitInitPAtScope(scope *scope, pos int) {
  191. if !b.isVar && scope.outer == nil {
  192. scope.c.p.code[pos] = initGlobalP(b.name)
  193. } else {
  194. b.markAccessPointAtScope(scope, pos)
  195. scope.c.p.code[pos] = initStackP(0)
  196. }
  197. }
  198. func (b *binding) emitGetVar(callee bool) {
  199. b.markAccessPoint()
  200. if b.isVar && !b.isArg {
  201. b.scope.c.emit(&loadMixed{name: b.name, callee: callee})
  202. } else {
  203. b.scope.c.emit(&loadMixedLex{name: b.name, callee: callee})
  204. }
  205. }
  206. func (b *binding) emitResolveVar(strict bool) {
  207. b.markAccessPoint()
  208. if b.isVar && !b.isArg {
  209. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: varTypeVar})
  210. } else {
  211. var typ varType
  212. if b.isConst {
  213. if b.isStrict {
  214. typ = varTypeStrictConst
  215. } else {
  216. typ = varTypeConst
  217. }
  218. } else {
  219. typ = varTypeLet
  220. }
  221. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: typ})
  222. }
  223. }
  224. func (b *binding) moveToStash() {
  225. if b.isArg && !b.scope.argsInStash {
  226. b.scope.moveArgsToStash()
  227. } else {
  228. b.inStash = true
  229. b.scope.needStash = true
  230. }
  231. }
  232. func (b *binding) useCount() (count int) {
  233. for _, a := range b.accessPoints {
  234. count += len(*a)
  235. }
  236. return
  237. }
  238. type scope struct {
  239. c *compiler
  240. prg *Program
  241. outer *scope
  242. nested []*scope
  243. boundNames map[unistring.String]*binding
  244. bindings []*binding
  245. base int
  246. numArgs int
  247. // function type. If not funcNone, this is a function or a top-level lexical environment
  248. funcType funcType
  249. // in strict mode
  250. strict bool
  251. // eval top-level scope
  252. eval bool
  253. // at least one inner scope has direct eval() which can lookup names dynamically (by name)
  254. dynLookup bool
  255. // at least one binding has been marked for placement in stash
  256. needStash bool
  257. // is a variable environment, i.e. the target for dynamically created var bindings
  258. variable bool
  259. // a function scope that has at least one direct eval() and non-strict, so the variables can be added dynamically
  260. dynamic bool
  261. // arguments have been marked for placement in stash (functions only)
  262. argsInStash bool
  263. // need 'arguments' object (functions only)
  264. argsNeeded bool
  265. }
  266. type block struct {
  267. typ blockType
  268. label unistring.String
  269. cont int
  270. breaks []int
  271. conts []int
  272. outer *block
  273. breaking *block // set when the 'finally' block is an empty break statement sequence
  274. needResult bool
  275. }
  276. func (c *compiler) leaveScopeBlock(enter *enterBlock) {
  277. c.updateEnterBlock(enter)
  278. leave := &leaveBlock{
  279. stackSize: enter.stackSize,
  280. popStash: enter.stashSize > 0,
  281. }
  282. c.emit(leave)
  283. for _, pc := range c.block.breaks {
  284. c.p.code[pc] = leave
  285. }
  286. c.block.breaks = nil
  287. c.leaveBlock()
  288. }
  289. func (c *compiler) leaveBlock() {
  290. lbl := len(c.p.code)
  291. for _, item := range c.block.breaks {
  292. c.p.code[item] = jump(lbl - item)
  293. }
  294. if t := c.block.typ; t == blockLoop || t == blockLoopEnum {
  295. for _, item := range c.block.conts {
  296. c.p.code[item] = jump(c.block.cont - item)
  297. }
  298. }
  299. c.block = c.block.outer
  300. }
  301. func (e *CompilerSyntaxError) Error() string {
  302. if e.File != nil {
  303. return fmt.Sprintf("SyntaxError: %s at %s", e.Message, e.File.Position(e.Offset))
  304. }
  305. return fmt.Sprintf("SyntaxError: %s", e.Message)
  306. }
  307. func (e *CompilerReferenceError) Error() string {
  308. return fmt.Sprintf("ReferenceError: %s", e.Message)
  309. }
  310. func (c *compiler) newScope() {
  311. strict := false
  312. if c.scope != nil {
  313. strict = c.scope.strict
  314. }
  315. c.scope = &scope{
  316. c: c,
  317. prg: c.p,
  318. outer: c.scope,
  319. strict: strict,
  320. }
  321. }
  322. func (c *compiler) newBlockScope() {
  323. c.newScope()
  324. if outer := c.scope.outer; outer != nil {
  325. outer.nested = append(outer.nested, c.scope)
  326. }
  327. c.scope.base = len(c.p.code)
  328. }
  329. func (c *compiler) popScope() {
  330. c.scope = c.scope.outer
  331. }
  332. func newCompiler() *compiler {
  333. c := &compiler{
  334. p: &Program{},
  335. }
  336. c.enumGetExpr.init(c, file.Idx(0))
  337. return c
  338. }
  339. func (p *Program) defineLiteralValue(val Value) uint32 {
  340. for idx, v := range p.values {
  341. if v.SameAs(val) {
  342. return uint32(idx)
  343. }
  344. }
  345. idx := uint32(len(p.values))
  346. p.values = append(p.values, val)
  347. return idx
  348. }
  349. func (p *Program) dumpCode(logger func(format string, args ...interface{})) {
  350. p._dumpCode("", logger)
  351. }
  352. func (p *Program) _dumpCode(indent string, logger func(format string, args ...interface{})) {
  353. logger("values: %+v", p.values)
  354. dumpInitFields := func(initFields *Program) {
  355. i := indent + ">"
  356. logger("%s ---- init_fields:", i)
  357. initFields._dumpCode(i, logger)
  358. logger("%s ----", i)
  359. }
  360. for pc, ins := range p.code {
  361. logger("%s %d: %T(%v)", indent, pc, ins, ins)
  362. var prg *Program
  363. switch f := ins.(type) {
  364. case newFuncInstruction:
  365. prg = f.getPrg()
  366. case *newDerivedClass:
  367. if f.initFields != nil {
  368. dumpInitFields(f.initFields)
  369. }
  370. prg = f.ctor
  371. case *newClass:
  372. if f.initFields != nil {
  373. dumpInitFields(f.initFields)
  374. }
  375. prg = f.ctor
  376. case *newStaticFieldInit:
  377. if f.initFields != nil {
  378. dumpInitFields(f.initFields)
  379. }
  380. }
  381. if prg != nil {
  382. prg._dumpCode(indent+">", logger)
  383. }
  384. }
  385. }
  386. func (p *Program) sourceOffset(pc int) int {
  387. i := sort.Search(len(p.srcMap), func(idx int) bool {
  388. return p.srcMap[idx].pc > pc
  389. }) - 1
  390. if i >= 0 {
  391. return p.srcMap[i].srcPos
  392. }
  393. return 0
  394. }
  395. func (p *Program) addSrcMap(srcPos int) {
  396. if len(p.srcMap) > 0 && p.srcMap[len(p.srcMap)-1].srcPos == srcPos {
  397. return
  398. }
  399. p.srcMap = append(p.srcMap, srcMapItem{pc: len(p.code), srcPos: srcPos})
  400. }
  401. func (s *scope) lookupName(name unistring.String) (binding *binding, noDynamics bool) {
  402. noDynamics = true
  403. toStash := false
  404. for curScope := s; ; curScope = curScope.outer {
  405. if curScope.outer != nil {
  406. if b, exists := curScope.boundNames[name]; exists {
  407. if toStash && !b.inStash {
  408. b.moveToStash()
  409. }
  410. binding = b
  411. return
  412. }
  413. } else {
  414. noDynamics = false
  415. return
  416. }
  417. if curScope.dynamic {
  418. noDynamics = false
  419. }
  420. if name == "arguments" && curScope.funcType != funcNone && curScope.funcType != funcArrow {
  421. if curScope.funcType == funcClsInit {
  422. s.c.throwSyntaxError(0, "'arguments' is not allowed in class field initializer or static initialization block")
  423. }
  424. curScope.argsNeeded = true
  425. binding, _ = curScope.bindName(name)
  426. return
  427. }
  428. if curScope.isFunction() {
  429. toStash = true
  430. }
  431. }
  432. }
  433. func (s *scope) lookupThis() (*binding, bool) {
  434. toStash := false
  435. for curScope := s; curScope != nil; curScope = curScope.outer {
  436. if curScope.outer == nil {
  437. if curScope.eval {
  438. return nil, true
  439. }
  440. }
  441. if b, exists := curScope.boundNames[thisBindingName]; exists {
  442. if toStash && !b.inStash {
  443. b.moveToStash()
  444. }
  445. return b, false
  446. }
  447. if curScope.isFunction() {
  448. toStash = true
  449. }
  450. }
  451. return nil, false
  452. }
  453. func (s *scope) ensureBoundNamesCreated() {
  454. if s.boundNames == nil {
  455. s.boundNames = make(map[unistring.String]*binding)
  456. }
  457. }
  458. func (s *scope) addBinding(offset int) *binding {
  459. if len(s.bindings) >= (1<<24)-1 {
  460. s.c.throwSyntaxError(offset, "Too many variables")
  461. }
  462. b := &binding{
  463. scope: s,
  464. }
  465. s.bindings = append(s.bindings, b)
  466. return b
  467. }
  468. func (s *scope) bindNameLexical(name unistring.String, unique bool, offset int) (*binding, bool) {
  469. if b := s.boundNames[name]; b != nil {
  470. if unique {
  471. s.c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  472. }
  473. return b, false
  474. }
  475. b := s.addBinding(offset)
  476. b.name = name
  477. s.ensureBoundNamesCreated()
  478. s.boundNames[name] = b
  479. return b, true
  480. }
  481. func (s *scope) createThisBinding() *binding {
  482. thisBinding, _ := s.bindNameLexical(thisBindingName, false, 0)
  483. thisBinding.isVar = true // don't check on load
  484. return thisBinding
  485. }
  486. func (s *scope) bindName(name unistring.String) (*binding, bool) {
  487. if !s.isFunction() && !s.variable && s.outer != nil {
  488. return s.outer.bindName(name)
  489. }
  490. b, created := s.bindNameLexical(name, false, 0)
  491. if created {
  492. b.isVar = true
  493. }
  494. return b, created
  495. }
  496. func (s *scope) bindNameShadow(name unistring.String) (*binding, bool) {
  497. if !s.isFunction() && s.outer != nil {
  498. return s.outer.bindNameShadow(name)
  499. }
  500. _, exists := s.boundNames[name]
  501. b := &binding{
  502. scope: s,
  503. name: name,
  504. }
  505. s.bindings = append(s.bindings, b)
  506. s.ensureBoundNamesCreated()
  507. s.boundNames[name] = b
  508. return b, !exists
  509. }
  510. func (s *scope) nearestFunction() *scope {
  511. for sc := s; sc != nil; sc = sc.outer {
  512. if sc.isFunction() {
  513. return sc
  514. }
  515. }
  516. return nil
  517. }
  518. func (s *scope) nearestThis() *scope {
  519. for sc := s; sc != nil; sc = sc.outer {
  520. if sc.eval || sc.isFunction() && sc.funcType != funcArrow {
  521. return sc
  522. }
  523. }
  524. return nil
  525. }
  526. func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
  527. argsInStash := false
  528. if f := s.nearestFunction(); f != nil {
  529. argsInStash = f.argsInStash
  530. }
  531. stackIdx, stashIdx := 0, 0
  532. allInStash := s.isDynamic()
  533. var derivedCtor bool
  534. if fs := s.nearestThis(); fs != nil && fs.funcType == funcDerivedCtor {
  535. derivedCtor = true
  536. }
  537. for i, b := range s.bindings {
  538. var this bool
  539. if b.name == thisBindingName {
  540. this = true
  541. }
  542. if allInStash || b.inStash {
  543. for scope, aps := range b.accessPoints {
  544. var level uint32
  545. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  546. if sc.needStash || sc.isDynamic() {
  547. level++
  548. }
  549. }
  550. if level > 255 {
  551. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  552. }
  553. idx := (level << 24) | uint32(stashIdx)
  554. base := scope.base
  555. code := scope.prg.code
  556. if this {
  557. if derivedCtor {
  558. for _, pc := range *aps {
  559. ap := &code[base+pc]
  560. switch (*ap).(type) {
  561. case loadStack:
  562. *ap = loadThisStash(idx)
  563. case initStack:
  564. *ap = initStash(idx)
  565. case resolveThisStack:
  566. *ap = resolveThisStash(idx)
  567. case _ret:
  568. *ap = cret(idx)
  569. default:
  570. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for 'this'")
  571. }
  572. }
  573. } else {
  574. for _, pc := range *aps {
  575. ap := &code[base+pc]
  576. switch (*ap).(type) {
  577. case loadStack:
  578. *ap = loadStash(idx)
  579. case initStack:
  580. *ap = initStash(idx)
  581. default:
  582. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for 'this'")
  583. }
  584. }
  585. }
  586. } else {
  587. for _, pc := range *aps {
  588. ap := &code[base+pc]
  589. switch i := (*ap).(type) {
  590. case loadStack:
  591. *ap = loadStash(idx)
  592. case storeStack:
  593. *ap = storeStash(idx)
  594. case storeStackP:
  595. *ap = storeStashP(idx)
  596. case loadStackLex:
  597. *ap = loadStashLex(idx)
  598. case storeStackLex:
  599. *ap = storeStashLex(idx)
  600. case storeStackLexP:
  601. *ap = storeStashLexP(idx)
  602. case initStackP:
  603. *ap = initStashP(idx)
  604. case initStack:
  605. *ap = initStash(idx)
  606. case *loadMixed:
  607. i.idx = idx
  608. case *loadMixedLex:
  609. i.idx = idx
  610. case *resolveMixed:
  611. i.idx = idx
  612. default:
  613. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for binding: %T", i)
  614. }
  615. }
  616. }
  617. }
  618. stashIdx++
  619. } else {
  620. var idx int
  621. if !this {
  622. if i < s.numArgs {
  623. idx = -(i + 1)
  624. } else {
  625. stackIdx++
  626. idx = stackIdx + stackOffset
  627. }
  628. }
  629. for scope, aps := range b.accessPoints {
  630. var level int
  631. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  632. if sc.needStash || sc.isDynamic() {
  633. level++
  634. }
  635. }
  636. if level > 255 {
  637. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  638. }
  639. code := scope.prg.code
  640. base := scope.base
  641. if this {
  642. if derivedCtor {
  643. for _, pc := range *aps {
  644. ap := &code[base+pc]
  645. switch (*ap).(type) {
  646. case loadStack:
  647. *ap = loadThisStack{}
  648. case initStack:
  649. // no-op
  650. case resolveThisStack:
  651. // no-op
  652. case _ret:
  653. // no-op, already in the right place
  654. default:
  655. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for 'this'")
  656. }
  657. }
  658. } /*else {
  659. no-op
  660. }*/
  661. } else if argsInStash {
  662. for _, pc := range *aps {
  663. ap := &code[base+pc]
  664. switch i := (*ap).(type) {
  665. case loadStack:
  666. *ap = loadStack1(idx)
  667. case storeStack:
  668. *ap = storeStack1(idx)
  669. case storeStackP:
  670. *ap = storeStack1P(idx)
  671. case loadStackLex:
  672. *ap = loadStack1Lex(idx)
  673. case storeStackLex:
  674. *ap = storeStack1Lex(idx)
  675. case storeStackLexP:
  676. *ap = storeStack1LexP(idx)
  677. case initStackP:
  678. *ap = initStack1P(idx)
  679. case initStack:
  680. *ap = initStack1(idx)
  681. case *loadMixed:
  682. *ap = &loadMixedStack1{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  683. case *loadMixedLex:
  684. *ap = &loadMixedStack1Lex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  685. case *resolveMixed:
  686. *ap = &resolveMixedStack1{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  687. default:
  688. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for binding: %T", i)
  689. }
  690. }
  691. } else {
  692. for _, pc := range *aps {
  693. ap := &code[base+pc]
  694. switch i := (*ap).(type) {
  695. case loadStack:
  696. *ap = loadStack(idx)
  697. case storeStack:
  698. *ap = storeStack(idx)
  699. case storeStackP:
  700. *ap = storeStackP(idx)
  701. case loadStackLex:
  702. *ap = loadStackLex(idx)
  703. case storeStackLex:
  704. *ap = storeStackLex(idx)
  705. case storeStackLexP:
  706. *ap = storeStackLexP(idx)
  707. case initStack:
  708. *ap = initStack(idx)
  709. case initStackP:
  710. *ap = initStackP(idx)
  711. case *loadMixed:
  712. *ap = &loadMixedStack{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  713. case *loadMixedLex:
  714. *ap = &loadMixedStackLex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  715. case *resolveMixed:
  716. *ap = &resolveMixedStack{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  717. default:
  718. s.c.assert(false, s.c.p.sourceOffset(pc), "Unsupported instruction for binding: %T", i)
  719. }
  720. }
  721. }
  722. }
  723. }
  724. }
  725. for _, nested := range s.nested {
  726. nested.finaliseVarAlloc(stackIdx + stackOffset)
  727. }
  728. return stashIdx, stackIdx
  729. }
  730. func (s *scope) moveArgsToStash() {
  731. for _, b := range s.bindings {
  732. if !b.isArg {
  733. break
  734. }
  735. b.inStash = true
  736. }
  737. s.argsInStash = true
  738. s.needStash = true
  739. }
  740. func (c *compiler) trimCode(delta int) {
  741. src := c.p.code[delta:]
  742. newCode := make([]instruction, len(src))
  743. copy(newCode, src)
  744. if cap(c.codeScratchpad) < cap(c.p.code) {
  745. c.codeScratchpad = c.p.code[:0]
  746. }
  747. c.p.code = newCode
  748. }
  749. func (s *scope) trimCode(delta int) {
  750. s.c.trimCode(delta)
  751. if delta != 0 {
  752. srcMap := s.c.p.srcMap
  753. for i := range srcMap {
  754. srcMap[i].pc -= delta
  755. }
  756. s.adjustBase(-delta)
  757. }
  758. }
  759. func (s *scope) adjustBase(delta int) {
  760. s.base += delta
  761. for _, nested := range s.nested {
  762. nested.adjustBase(delta)
  763. }
  764. }
  765. func (s *scope) makeNamesMap() map[unistring.String]uint32 {
  766. l := len(s.bindings)
  767. if l == 0 {
  768. return nil
  769. }
  770. names := make(map[unistring.String]uint32, l)
  771. for i, b := range s.bindings {
  772. idx := uint32(i)
  773. if b.isConst {
  774. idx |= maskConst
  775. if b.isStrict {
  776. idx |= maskStrict
  777. }
  778. }
  779. if b.isVar {
  780. idx |= maskVar
  781. }
  782. names[b.name] = idx
  783. }
  784. return names
  785. }
  786. func (s *scope) isDynamic() bool {
  787. return s.dynLookup || s.dynamic
  788. }
  789. func (s *scope) isFunction() bool {
  790. return s.funcType != funcNone && !s.eval
  791. }
  792. func (s *scope) deleteBinding(b *binding) {
  793. idx := 0
  794. for i, bb := range s.bindings {
  795. if bb == b {
  796. idx = i
  797. goto found
  798. }
  799. }
  800. return
  801. found:
  802. delete(s.boundNames, b.name)
  803. copy(s.bindings[idx:], s.bindings[idx+1:])
  804. l := len(s.bindings) - 1
  805. s.bindings[l] = nil
  806. s.bindings = s.bindings[:l]
  807. }
  808. func (c *compiler) compile(in *ast.Program, strict, inGlobal bool, evalVm *vm) {
  809. c.ctxVM = evalVm
  810. eval := evalVm != nil
  811. c.p.src = in.File
  812. c.newScope()
  813. scope := c.scope
  814. scope.dynamic = true
  815. scope.eval = eval
  816. if !strict && len(in.Body) > 0 {
  817. strict = c.isStrict(in.Body) != nil
  818. }
  819. scope.strict = strict
  820. ownVarScope := eval && strict
  821. ownLexScope := !inGlobal || eval
  822. if ownVarScope {
  823. c.newBlockScope()
  824. scope = c.scope
  825. scope.variable = true
  826. }
  827. if eval && !inGlobal {
  828. for s := evalVm.stash; s != nil; s = s.outer {
  829. if ft := s.funcType; ft != funcNone && ft != funcArrow {
  830. scope.funcType = ft
  831. break
  832. }
  833. }
  834. }
  835. funcs := c.extractFunctions(in.Body)
  836. c.createFunctionBindings(funcs)
  837. numFuncs := len(scope.bindings)
  838. if inGlobal && !ownVarScope {
  839. if numFuncs == len(funcs) {
  840. c.compileFunctionsGlobalAllUnique(funcs)
  841. } else {
  842. c.compileFunctionsGlobal(funcs)
  843. }
  844. }
  845. c.compileDeclList(in.DeclarationList, false)
  846. numVars := len(scope.bindings) - numFuncs
  847. vars := make([]unistring.String, len(scope.bindings))
  848. for i, b := range scope.bindings {
  849. vars[i] = b.name
  850. }
  851. if len(vars) > 0 && !ownVarScope && ownLexScope {
  852. if inGlobal {
  853. c.emit(&bindGlobal{
  854. vars: vars[numFuncs:],
  855. funcs: vars[:numFuncs],
  856. deletable: eval,
  857. })
  858. } else {
  859. c.emit(&bindVars{names: vars, deletable: eval})
  860. }
  861. }
  862. var enter *enterBlock
  863. if c.compileLexicalDeclarations(in.Body, ownVarScope || !ownLexScope) {
  864. if ownLexScope {
  865. c.block = &block{
  866. outer: c.block,
  867. typ: blockScope,
  868. needResult: true,
  869. }
  870. enter = &enterBlock{}
  871. c.emit(enter)
  872. }
  873. }
  874. if len(scope.bindings) > 0 && !ownLexScope {
  875. var lets, consts []unistring.String
  876. for _, b := range c.scope.bindings[numFuncs+numVars:] {
  877. if b.isConst {
  878. consts = append(consts, b.name)
  879. } else {
  880. lets = append(lets, b.name)
  881. }
  882. }
  883. c.emit(&bindGlobal{
  884. vars: vars[numFuncs:],
  885. funcs: vars[:numFuncs],
  886. lets: lets,
  887. consts: consts,
  888. })
  889. }
  890. if !inGlobal || ownVarScope {
  891. c.compileFunctions(funcs)
  892. }
  893. c.compileStatements(in.Body, true)
  894. if enter != nil {
  895. c.leaveScopeBlock(enter)
  896. c.popScope()
  897. }
  898. scope.finaliseVarAlloc(0)
  899. }
  900. func (c *compiler) compileDeclList(v []*ast.VariableDeclaration, inFunc bool) {
  901. for _, value := range v {
  902. c.createVarBindings(value, inFunc)
  903. }
  904. }
  905. func (c *compiler) extractLabelled(st ast.Statement) ast.Statement {
  906. if st, ok := st.(*ast.LabelledStatement); ok {
  907. return c.extractLabelled(st.Statement)
  908. }
  909. return st
  910. }
  911. func (c *compiler) extractFunctions(list []ast.Statement) (funcs []*ast.FunctionDeclaration) {
  912. for _, st := range list {
  913. var decl *ast.FunctionDeclaration
  914. switch st := c.extractLabelled(st).(type) {
  915. case *ast.FunctionDeclaration:
  916. decl = st
  917. case *ast.LabelledStatement:
  918. if st1, ok := st.Statement.(*ast.FunctionDeclaration); ok {
  919. decl = st1
  920. } else {
  921. continue
  922. }
  923. default:
  924. continue
  925. }
  926. funcs = append(funcs, decl)
  927. }
  928. return
  929. }
  930. func (c *compiler) createFunctionBindings(funcs []*ast.FunctionDeclaration) {
  931. s := c.scope
  932. if s.outer != nil {
  933. unique := !s.isFunction() && !s.variable && s.strict
  934. if !unique {
  935. hasNonStandard := false
  936. for _, decl := range funcs {
  937. if !decl.Function.Async && !decl.Function.Generator {
  938. s.bindNameLexical(decl.Function.Name.Name, false, int(decl.Function.Name.Idx1())-1)
  939. } else {
  940. hasNonStandard = true
  941. }
  942. }
  943. if hasNonStandard {
  944. for _, decl := range funcs {
  945. if decl.Function.Async || decl.Function.Generator {
  946. s.bindNameLexical(decl.Function.Name.Name, true, int(decl.Function.Name.Idx1())-1)
  947. }
  948. }
  949. }
  950. } else {
  951. for _, decl := range funcs {
  952. s.bindNameLexical(decl.Function.Name.Name, true, int(decl.Function.Name.Idx1())-1)
  953. }
  954. }
  955. } else {
  956. for _, decl := range funcs {
  957. s.bindName(decl.Function.Name.Name)
  958. }
  959. }
  960. }
  961. func (c *compiler) compileFunctions(list []*ast.FunctionDeclaration) {
  962. for _, decl := range list {
  963. c.compileFunction(decl)
  964. }
  965. }
  966. func (c *compiler) compileFunctionsGlobalAllUnique(list []*ast.FunctionDeclaration) {
  967. for _, decl := range list {
  968. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  969. }
  970. }
  971. func (c *compiler) compileFunctionsGlobal(list []*ast.FunctionDeclaration) {
  972. m := make(map[unistring.String]int, len(list))
  973. for i := len(list) - 1; i >= 0; i-- {
  974. name := list[i].Function.Name.Name
  975. if _, exists := m[name]; !exists {
  976. m[name] = i
  977. }
  978. }
  979. idx := 0
  980. for i, decl := range list {
  981. name := decl.Function.Name.Name
  982. if m[name] == i {
  983. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  984. c.scope.bindings[idx] = c.scope.boundNames[name]
  985. idx++
  986. } else {
  987. leave := c.enterDummyMode()
  988. c.compileFunctionLiteral(decl.Function, false).emitGetter(false)
  989. leave()
  990. }
  991. }
  992. }
  993. func (c *compiler) createVarIdBinding(name unistring.String, offset int, inFunc bool) {
  994. if c.scope.strict {
  995. c.checkIdentifierLName(name, offset)
  996. c.checkIdentifierName(name, offset)
  997. }
  998. if !inFunc || name != "arguments" {
  999. c.scope.bindName(name)
  1000. }
  1001. }
  1002. func (c *compiler) createBindings(target ast.Expression, createIdBinding func(name unistring.String, offset int)) {
  1003. switch target := target.(type) {
  1004. case *ast.Identifier:
  1005. createIdBinding(target.Name, int(target.Idx)-1)
  1006. case *ast.ObjectPattern:
  1007. for _, prop := range target.Properties {
  1008. switch prop := prop.(type) {
  1009. case *ast.PropertyShort:
  1010. createIdBinding(prop.Name.Name, int(prop.Name.Idx)-1)
  1011. case *ast.PropertyKeyed:
  1012. c.createBindings(prop.Value, createIdBinding)
  1013. default:
  1014. c.throwSyntaxError(int(target.Idx0()-1), "unsupported property type in ObjectPattern: %T", prop)
  1015. }
  1016. }
  1017. if target.Rest != nil {
  1018. c.createBindings(target.Rest, createIdBinding)
  1019. }
  1020. case *ast.ArrayPattern:
  1021. for _, elt := range target.Elements {
  1022. if elt != nil {
  1023. c.createBindings(elt, createIdBinding)
  1024. }
  1025. }
  1026. if target.Rest != nil {
  1027. c.createBindings(target.Rest, createIdBinding)
  1028. }
  1029. case *ast.AssignExpression:
  1030. c.createBindings(target.Left, createIdBinding)
  1031. default:
  1032. c.throwSyntaxError(int(target.Idx0()-1), "unsupported binding target: %T", target)
  1033. }
  1034. }
  1035. func (c *compiler) createVarBinding(target ast.Expression, inFunc bool) {
  1036. c.createBindings(target, func(name unistring.String, offset int) {
  1037. c.createVarIdBinding(name, offset, inFunc)
  1038. })
  1039. }
  1040. func (c *compiler) createVarBindings(v *ast.VariableDeclaration, inFunc bool) {
  1041. for _, item := range v.List {
  1042. c.createVarBinding(item.Target, inFunc)
  1043. }
  1044. }
  1045. func (c *compiler) createLexicalIdBinding(name unistring.String, isConst bool, offset int) *binding {
  1046. if name == "let" {
  1047. c.throwSyntaxError(offset, "let is disallowed as a lexically bound name")
  1048. }
  1049. if c.scope.strict {
  1050. c.checkIdentifierLName(name, offset)
  1051. c.checkIdentifierName(name, offset)
  1052. }
  1053. b, _ := c.scope.bindNameLexical(name, true, offset)
  1054. if isConst {
  1055. b.isConst, b.isStrict = true, true
  1056. }
  1057. return b
  1058. }
  1059. func (c *compiler) createLexicalIdBindingFuncBody(name unistring.String, isConst bool, offset int, calleeBinding *binding) *binding {
  1060. if name == "let" {
  1061. c.throwSyntaxError(offset, "let is disallowed as a lexically bound name")
  1062. }
  1063. if c.scope.strict {
  1064. c.checkIdentifierLName(name, offset)
  1065. c.checkIdentifierName(name, offset)
  1066. }
  1067. paramScope := c.scope.outer
  1068. parentBinding := paramScope.boundNames[name]
  1069. if parentBinding != nil {
  1070. if parentBinding != calleeBinding && (name != "arguments" || !paramScope.argsNeeded) {
  1071. c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  1072. }
  1073. }
  1074. b, _ := c.scope.bindNameLexical(name, true, offset)
  1075. if isConst {
  1076. b.isConst, b.isStrict = true, true
  1077. }
  1078. return b
  1079. }
  1080. func (c *compiler) createLexicalBinding(target ast.Expression, isConst bool) {
  1081. c.createBindings(target, func(name unistring.String, offset int) {
  1082. c.createLexicalIdBinding(name, isConst, offset)
  1083. })
  1084. }
  1085. func (c *compiler) createLexicalBindings(lex *ast.LexicalDeclaration) {
  1086. for _, d := range lex.List {
  1087. c.createLexicalBinding(d.Target, lex.Token == token.CONST)
  1088. }
  1089. }
  1090. func (c *compiler) compileLexicalDeclarations(list []ast.Statement, scopeDeclared bool) bool {
  1091. for _, st := range list {
  1092. if lex, ok := st.(*ast.LexicalDeclaration); ok {
  1093. if !scopeDeclared {
  1094. c.newBlockScope()
  1095. scopeDeclared = true
  1096. }
  1097. c.createLexicalBindings(lex)
  1098. } else if cls, ok := st.(*ast.ClassDeclaration); ok {
  1099. if !scopeDeclared {
  1100. c.newBlockScope()
  1101. scopeDeclared = true
  1102. }
  1103. c.createLexicalIdBinding(cls.Class.Name.Name, false, int(cls.Class.Name.Idx)-1)
  1104. }
  1105. }
  1106. return scopeDeclared
  1107. }
  1108. func (c *compiler) compileLexicalDeclarationsFuncBody(list []ast.Statement, calleeBinding *binding) {
  1109. for _, st := range list {
  1110. if lex, ok := st.(*ast.LexicalDeclaration); ok {
  1111. isConst := lex.Token == token.CONST
  1112. for _, d := range lex.List {
  1113. c.createBindings(d.Target, func(name unistring.String, offset int) {
  1114. c.createLexicalIdBindingFuncBody(name, isConst, offset, calleeBinding)
  1115. })
  1116. }
  1117. } else if cls, ok := st.(*ast.ClassDeclaration); ok {
  1118. c.createLexicalIdBindingFuncBody(cls.Class.Name.Name, false, int(cls.Class.Name.Idx)-1, calleeBinding)
  1119. }
  1120. }
  1121. }
  1122. func (c *compiler) compileFunction(v *ast.FunctionDeclaration) {
  1123. name := v.Function.Name.Name
  1124. b := c.scope.boundNames[name]
  1125. if b == nil || b.isVar {
  1126. e := &compiledIdentifierExpr{
  1127. name: v.Function.Name.Name,
  1128. }
  1129. e.init(c, v.Function.Idx0())
  1130. e.emitSetter(c.compileFunctionLiteral(v.Function, false), false)
  1131. } else {
  1132. c.compileFunctionLiteral(v.Function, false).emitGetter(true)
  1133. b.emitInitP()
  1134. }
  1135. }
  1136. func (c *compiler) compileStandaloneFunctionDecl(v *ast.FunctionDeclaration) {
  1137. if v.Function.Async {
  1138. c.throwSyntaxError(int(v.Idx0())-1, "Async functions can only be declared at top level or inside a block.")
  1139. }
  1140. if v.Function.Generator {
  1141. c.throwSyntaxError(int(v.Idx0())-1, "Generators can only be declared at top level or inside a block.")
  1142. }
  1143. if c.scope.strict {
  1144. c.throwSyntaxError(int(v.Idx0())-1, "In strict mode code, functions can only be declared at top level or inside a block.")
  1145. }
  1146. c.throwSyntaxError(int(v.Idx0())-1, "In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement.")
  1147. }
  1148. func (c *compiler) emit(instructions ...instruction) {
  1149. c.p.code = append(c.p.code, instructions...)
  1150. }
  1151. func (c *compiler) throwSyntaxError(offset int, format string, args ...interface{}) {
  1152. panic(&CompilerSyntaxError{
  1153. CompilerError: CompilerError{
  1154. File: c.p.src,
  1155. Offset: offset,
  1156. Message: fmt.Sprintf(format, args...),
  1157. },
  1158. })
  1159. }
  1160. func (c *compiler) isStrict(list []ast.Statement) *ast.StringLiteral {
  1161. for _, st := range list {
  1162. if st, ok := st.(*ast.ExpressionStatement); ok {
  1163. if e, ok := st.Expression.(*ast.StringLiteral); ok {
  1164. if e.Literal == `"use strict"` || e.Literal == `'use strict'` {
  1165. return e
  1166. }
  1167. } else {
  1168. break
  1169. }
  1170. } else {
  1171. break
  1172. }
  1173. }
  1174. return nil
  1175. }
  1176. func (c *compiler) isStrictStatement(s ast.Statement) *ast.StringLiteral {
  1177. if s, ok := s.(*ast.BlockStatement); ok {
  1178. return c.isStrict(s.List)
  1179. }
  1180. return nil
  1181. }
  1182. func (c *compiler) checkIdentifierName(name unistring.String, offset int) {
  1183. switch name {
  1184. case "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield":
  1185. c.throwSyntaxError(offset, "Unexpected strict mode reserved word")
  1186. }
  1187. }
  1188. func (c *compiler) checkIdentifierLName(name unistring.String, offset int) {
  1189. switch name {
  1190. case "eval", "arguments":
  1191. c.throwSyntaxError(offset, "Assignment to eval or arguments is not allowed in strict mode")
  1192. }
  1193. }
  1194. // Enter a 'dummy' compilation mode. Any code produced after this method is called will be discarded after
  1195. // leaveFunc is called with no additional side effects. This is useful for compiling code inside a
  1196. // constant falsy condition 'if' branch or a loop (i.e 'if (false) { ... } or while (false) { ... }).
  1197. // Such code should not be included in the final compilation result as it's never called, but it must
  1198. // still produce compilation errors if there are any.
  1199. // TODO: make sure variable lookups do not de-optimise parent scopes
  1200. func (c *compiler) enterDummyMode() (leaveFunc func()) {
  1201. savedBlock, savedProgram := c.block, c.p
  1202. if savedBlock != nil {
  1203. c.block = &block{
  1204. typ: savedBlock.typ,
  1205. label: savedBlock.label,
  1206. outer: savedBlock.outer,
  1207. breaking: savedBlock.breaking,
  1208. }
  1209. }
  1210. c.p = &Program{
  1211. src: c.p.src,
  1212. }
  1213. c.newScope()
  1214. return func() {
  1215. c.block, c.p = savedBlock, savedProgram
  1216. c.popScope()
  1217. }
  1218. }
  1219. func (c *compiler) compileStatementDummy(statement ast.Statement) {
  1220. leave := c.enterDummyMode()
  1221. c.compileStatement(statement, false)
  1222. leave()
  1223. }
  1224. func (c *compiler) assert(cond bool, offset int, msg string, args ...interface{}) {
  1225. if !cond {
  1226. c.throwSyntaxError(offset, "Compiler bug: "+msg, args...)
  1227. }
  1228. }
  1229. func privateIdString(desc unistring.String) unistring.String {
  1230. return asciiString("#").Concat(stringValueFromRaw(desc)).string()
  1231. }
  1232. type privateName struct {
  1233. idx int
  1234. isStatic bool
  1235. isMethod bool
  1236. hasGetter, hasSetter bool
  1237. }
  1238. type resolvedPrivateName struct {
  1239. name unistring.String
  1240. idx uint32
  1241. level uint8
  1242. isStatic bool
  1243. isMethod bool
  1244. }
  1245. func (r *resolvedPrivateName) string() unistring.String {
  1246. return privateIdString(r.name)
  1247. }
  1248. type privateEnvRegistry struct {
  1249. fields, methods []unistring.String
  1250. }
  1251. type classScope struct {
  1252. c *compiler
  1253. privateNames map[unistring.String]*privateName
  1254. instanceEnv, staticEnv privateEnvRegistry
  1255. outer *classScope
  1256. }
  1257. func (r *privateEnvRegistry) createPrivateMethodId(name unistring.String) int {
  1258. r.methods = append(r.methods, name)
  1259. return len(r.methods) - 1
  1260. }
  1261. func (r *privateEnvRegistry) createPrivateFieldId(name unistring.String) int {
  1262. r.fields = append(r.fields, name)
  1263. return len(r.fields) - 1
  1264. }
  1265. func (s *classScope) declarePrivateId(name unistring.String, kind ast.PropertyKind, isStatic bool, offset int) {
  1266. pn := s.privateNames[name]
  1267. if pn != nil {
  1268. if pn.isStatic == isStatic {
  1269. switch kind {
  1270. case ast.PropertyKindGet:
  1271. if pn.hasSetter && !pn.hasGetter {
  1272. pn.hasGetter = true
  1273. return
  1274. }
  1275. case ast.PropertyKindSet:
  1276. if pn.hasGetter && !pn.hasSetter {
  1277. pn.hasSetter = true
  1278. return
  1279. }
  1280. }
  1281. }
  1282. s.c.throwSyntaxError(offset, "Identifier '#%s' has already been declared", name)
  1283. panic("unreachable")
  1284. }
  1285. var env *privateEnvRegistry
  1286. if isStatic {
  1287. env = &s.staticEnv
  1288. } else {
  1289. env = &s.instanceEnv
  1290. }
  1291. pn = &privateName{
  1292. isStatic: isStatic,
  1293. hasGetter: kind == ast.PropertyKindGet,
  1294. hasSetter: kind == ast.PropertyKindSet,
  1295. }
  1296. if kind != ast.PropertyKindValue {
  1297. pn.idx = env.createPrivateMethodId(name)
  1298. pn.isMethod = true
  1299. } else {
  1300. pn.idx = env.createPrivateFieldId(name)
  1301. }
  1302. if s.privateNames == nil {
  1303. s.privateNames = make(map[unistring.String]*privateName)
  1304. }
  1305. s.privateNames[name] = pn
  1306. }
  1307. func (s *classScope) getDeclaredPrivateId(name unistring.String) *privateName {
  1308. if n := s.privateNames[name]; n != nil {
  1309. return n
  1310. }
  1311. s.c.assert(false, 0, "getDeclaredPrivateId() for undeclared id")
  1312. panic("unreachable")
  1313. }
  1314. func (c *compiler) resolvePrivateName(name unistring.String, offset int) (*resolvedPrivateName, *privateId) {
  1315. level := 0
  1316. for s := c.classScope; s != nil; s = s.outer {
  1317. if len(s.privateNames) > 0 {
  1318. if pn := s.privateNames[name]; pn != nil {
  1319. return &resolvedPrivateName{
  1320. name: name,
  1321. idx: uint32(pn.idx),
  1322. level: uint8(level),
  1323. isStatic: pn.isStatic,
  1324. isMethod: pn.isMethod,
  1325. }, nil
  1326. }
  1327. level++
  1328. }
  1329. }
  1330. if c.ctxVM != nil {
  1331. for s := c.ctxVM.privEnv; s != nil; s = s.outer {
  1332. if id := s.names[name]; id != nil {
  1333. return nil, id
  1334. }
  1335. }
  1336. }
  1337. c.throwSyntaxError(offset, "Private field '#%s' must be declared in an enclosing class", name)
  1338. panic("unreachable")
  1339. }