compiler.go 34 KB

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