compiler.go 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  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. )
  21. const (
  22. maskConst = 1 << 31
  23. maskVar = 1 << 30
  24. maskDeletable = 1 << 29
  25. maskStrict = maskDeletable
  26. maskTyp = maskConst | maskVar | maskDeletable
  27. )
  28. type varType byte
  29. const (
  30. varTypeVar varType = iota
  31. varTypeLet
  32. varTypeStrictConst
  33. varTypeConst
  34. )
  35. type CompilerError struct {
  36. Message string
  37. File *file.File
  38. Offset int
  39. }
  40. type CompilerSyntaxError struct {
  41. CompilerError
  42. }
  43. type CompilerReferenceError struct {
  44. CompilerError
  45. }
  46. type srcMapItem struct {
  47. pc int
  48. srcPos int
  49. }
  50. type Program struct {
  51. code []instruction
  52. values []Value
  53. funcName unistring.String
  54. src *file.File
  55. srcMap []srcMapItem
  56. }
  57. type compiler struct {
  58. p *Program
  59. scope *scope
  60. block *block
  61. enumGetExpr compiledEnumGetExpr
  62. evalVM *vm
  63. }
  64. type binding struct {
  65. scope *scope
  66. name unistring.String
  67. accessPoints map[*scope]*[]int
  68. isConst bool
  69. isStrict bool
  70. isArg bool
  71. isVar bool
  72. inStash bool
  73. }
  74. func (b *binding) getAccessPointsForScope(s *scope) *[]int {
  75. m := b.accessPoints[s]
  76. if m == nil {
  77. a := make([]int, 0, 1)
  78. m = &a
  79. if b.accessPoints == nil {
  80. b.accessPoints = make(map[*scope]*[]int)
  81. }
  82. b.accessPoints[s] = m
  83. }
  84. return m
  85. }
  86. func (b *binding) markAccessPointAt(pos int) {
  87. scope := b.scope.c.scope
  88. m := b.getAccessPointsForScope(scope)
  89. *m = append(*m, pos-scope.base)
  90. }
  91. func (b *binding) markAccessPointAtScope(scope *scope, pos int) {
  92. m := b.getAccessPointsForScope(scope)
  93. *m = append(*m, pos-scope.base)
  94. }
  95. func (b *binding) markAccessPoint() {
  96. scope := b.scope.c.scope
  97. m := b.getAccessPointsForScope(scope)
  98. *m = append(*m, len(scope.prg.code)-scope.base)
  99. }
  100. func (b *binding) emitGet() {
  101. b.markAccessPoint()
  102. if b.isVar && !b.isArg {
  103. b.scope.c.emit(loadStash(0))
  104. } else {
  105. b.scope.c.emit(loadStashLex(0))
  106. }
  107. }
  108. func (b *binding) emitGetAt(pos int) {
  109. b.markAccessPointAt(pos)
  110. if b.isVar && !b.isArg {
  111. b.scope.c.p.code[pos] = loadStash(0)
  112. } else {
  113. b.scope.c.p.code[pos] = loadStashLex(0)
  114. }
  115. }
  116. func (b *binding) emitGetP() {
  117. if b.isVar && !b.isArg {
  118. // no-op
  119. } else {
  120. // make sure TDZ is checked
  121. b.markAccessPoint()
  122. b.scope.c.emit(loadStashLex(0), pop)
  123. }
  124. }
  125. func (b *binding) emitSet() {
  126. if b.isConst {
  127. if b.isStrict || b.scope.c.scope.strict {
  128. b.scope.c.emit(throwAssignToConst)
  129. }
  130. return
  131. }
  132. b.markAccessPoint()
  133. if b.isVar && !b.isArg {
  134. b.scope.c.emit(storeStash(0))
  135. } else {
  136. b.scope.c.emit(storeStashLex(0))
  137. }
  138. }
  139. func (b *binding) emitSetP() {
  140. if b.isConst {
  141. if b.isStrict || b.scope.c.scope.strict {
  142. b.scope.c.emit(throwAssignToConst)
  143. }
  144. return
  145. }
  146. b.markAccessPoint()
  147. if b.isVar && !b.isArg {
  148. b.scope.c.emit(storeStashP(0))
  149. } else {
  150. b.scope.c.emit(storeStashLexP(0))
  151. }
  152. }
  153. func (b *binding) emitInit() {
  154. b.markAccessPoint()
  155. b.scope.c.emit(initStash(0))
  156. }
  157. func (b *binding) emitGetVar(callee bool) {
  158. b.markAccessPoint()
  159. if b.isVar && !b.isArg {
  160. b.scope.c.emit(&loadMixed{name: b.name, callee: callee})
  161. } else {
  162. b.scope.c.emit(&loadMixedLex{name: b.name, callee: callee})
  163. }
  164. }
  165. func (b *binding) emitResolveVar(strict bool) {
  166. b.markAccessPoint()
  167. if b.isVar && !b.isArg {
  168. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: varTypeVar})
  169. } else {
  170. var typ varType
  171. if b.isConst {
  172. if b.isStrict {
  173. typ = varTypeStrictConst
  174. } else {
  175. typ = varTypeConst
  176. }
  177. } else {
  178. typ = varTypeLet
  179. }
  180. b.scope.c.emit(&resolveMixed{name: b.name, strict: strict, typ: typ})
  181. }
  182. }
  183. func (b *binding) moveToStash() {
  184. if b.isArg && !b.scope.argsInStash {
  185. b.scope.moveArgsToStash()
  186. } else {
  187. b.inStash = true
  188. b.scope.needStash = true
  189. }
  190. }
  191. func (b *binding) useCount() (count int) {
  192. for _, a := range b.accessPoints {
  193. count += len(*a)
  194. }
  195. return
  196. }
  197. type scope struct {
  198. c *compiler
  199. prg *Program
  200. outer *scope
  201. nested []*scope
  202. boundNames map[unistring.String]*binding
  203. bindings []*binding
  204. base int
  205. numArgs int
  206. // in strict mode
  207. strict bool
  208. // eval top-level scope
  209. eval bool
  210. // at least one inner scope has direct eval() which can lookup names dynamically (by name)
  211. dynLookup bool
  212. // at least one binding has been marked for placement in stash
  213. needStash bool
  214. // is a function or a top-level lexical environment
  215. function bool
  216. // is a variable environment, i.e. the target for dynamically created var bindings
  217. variable bool
  218. // a function scope that has at least one direct eval() and non-strict, so the variables can be added dynamically
  219. dynamic bool
  220. // arguments have been marked for placement in stash (functions only)
  221. argsInStash bool
  222. // need 'arguments' object (functions only)
  223. argsNeeded bool
  224. // 'this' is used and non-strict, so need to box it (functions only)
  225. thisNeeded bool
  226. }
  227. type block struct {
  228. typ blockType
  229. label unistring.String
  230. cont int
  231. breaks []int
  232. conts []int
  233. outer *block
  234. breaking *block // set when the 'finally' block is an empty break statement sequence
  235. needResult bool
  236. }
  237. func (c *compiler) leaveScopeBlock(enter *enterBlock) {
  238. c.updateEnterBlock(enter)
  239. leave := &leaveBlock{
  240. stackSize: enter.stackSize,
  241. popStash: enter.stashSize > 0,
  242. }
  243. c.emit(leave)
  244. for _, pc := range c.block.breaks {
  245. c.p.code[pc] = leave
  246. }
  247. c.block.breaks = nil
  248. c.leaveBlock()
  249. }
  250. func (c *compiler) leaveBlock() {
  251. lbl := len(c.p.code)
  252. for _, item := range c.block.breaks {
  253. c.p.code[item] = jump(lbl - item)
  254. }
  255. if t := c.block.typ; t == blockLoop || t == blockLoopEnum {
  256. for _, item := range c.block.conts {
  257. c.p.code[item] = jump(c.block.cont - item)
  258. }
  259. }
  260. c.block = c.block.outer
  261. }
  262. func (e *CompilerSyntaxError) Error() string {
  263. if e.File != nil {
  264. return fmt.Sprintf("SyntaxError: %s at %s", e.Message, e.File.Position(e.Offset))
  265. }
  266. return fmt.Sprintf("SyntaxError: %s", e.Message)
  267. }
  268. func (e *CompilerReferenceError) Error() string {
  269. return fmt.Sprintf("ReferenceError: %s", e.Message)
  270. }
  271. func (c *compiler) newScope() {
  272. strict := false
  273. if c.scope != nil {
  274. strict = c.scope.strict
  275. }
  276. c.scope = &scope{
  277. c: c,
  278. prg: c.p,
  279. outer: c.scope,
  280. strict: strict,
  281. }
  282. }
  283. func (c *compiler) newBlockScope() {
  284. c.newScope()
  285. if outer := c.scope.outer; outer != nil {
  286. outer.nested = append(outer.nested, c.scope)
  287. }
  288. c.scope.base = len(c.p.code)
  289. }
  290. func (c *compiler) popScope() {
  291. c.scope = c.scope.outer
  292. }
  293. func newCompiler() *compiler {
  294. c := &compiler{
  295. p: &Program{},
  296. }
  297. c.enumGetExpr.init(c, file.Idx(0))
  298. return c
  299. }
  300. func (p *Program) defineLiteralValue(val Value) uint32 {
  301. for idx, v := range p.values {
  302. if v.SameAs(val) {
  303. return uint32(idx)
  304. }
  305. }
  306. idx := uint32(len(p.values))
  307. p.values = append(p.values, val)
  308. return idx
  309. }
  310. func (p *Program) dumpCode(logger func(format string, args ...interface{})) {
  311. p._dumpCode("", logger)
  312. }
  313. func (p *Program) _dumpCode(indent string, logger func(format string, args ...interface{})) {
  314. logger("values: %+v", p.values)
  315. for pc, ins := range p.code {
  316. logger("%s %d: %T(%v)", indent, pc, ins, ins)
  317. if f, ok := ins.(*newFunc); ok {
  318. f.prg._dumpCode(indent+">", logger)
  319. }
  320. }
  321. }
  322. func (p *Program) sourceOffset(pc int) int {
  323. i := sort.Search(len(p.srcMap), func(idx int) bool {
  324. return p.srcMap[idx].pc > pc
  325. }) - 1
  326. if i >= 0 {
  327. return p.srcMap[i].srcPos
  328. }
  329. return 0
  330. }
  331. func (s *scope) lookupName(name unistring.String) (binding *binding, noDynamics bool) {
  332. noDynamics = true
  333. toStash := false
  334. for curScope := s; curScope != nil; curScope = curScope.outer {
  335. if curScope.dynamic {
  336. noDynamics = false
  337. } else {
  338. if b, exists := curScope.boundNames[name]; exists {
  339. if toStash && !b.inStash {
  340. b.moveToStash()
  341. }
  342. binding = b
  343. return
  344. }
  345. }
  346. if name == "arguments" && curScope.function {
  347. curScope.argsNeeded = true
  348. binding, _ = curScope.bindName(name)
  349. return
  350. }
  351. if curScope.function {
  352. toStash = true
  353. }
  354. }
  355. return
  356. }
  357. func (s *scope) ensureBoundNamesCreated() {
  358. if s.boundNames == nil {
  359. s.boundNames = make(map[unistring.String]*binding)
  360. }
  361. }
  362. func (s *scope) addBinding(offset int) *binding {
  363. if len(s.bindings) >= (1<<24)-1 {
  364. s.c.throwSyntaxError(offset, "Too many variables")
  365. }
  366. b := &binding{
  367. scope: s,
  368. }
  369. s.bindings = append(s.bindings, b)
  370. return b
  371. }
  372. func (s *scope) bindNameLexical(name unistring.String, unique bool, offset int) (*binding, bool) {
  373. if b := s.boundNames[name]; b != nil {
  374. if unique {
  375. s.c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  376. }
  377. return b, false
  378. }
  379. b := s.addBinding(offset)
  380. b.name = name
  381. s.ensureBoundNamesCreated()
  382. s.boundNames[name] = b
  383. return b, true
  384. }
  385. func (s *scope) bindName(name unistring.String) (*binding, bool) {
  386. if !s.function && !s.variable && s.outer != nil {
  387. return s.outer.bindName(name)
  388. }
  389. b, created := s.bindNameLexical(name, false, 0)
  390. if created {
  391. b.isVar = true
  392. }
  393. return b, created
  394. }
  395. func (s *scope) bindNameShadow(name unistring.String) (*binding, bool) {
  396. if !s.function && s.outer != nil {
  397. return s.outer.bindNameShadow(name)
  398. }
  399. _, exists := s.boundNames[name]
  400. b := &binding{
  401. scope: s,
  402. name: name,
  403. }
  404. s.bindings = append(s.bindings, b)
  405. s.ensureBoundNamesCreated()
  406. s.boundNames[name] = b
  407. return b, !exists
  408. }
  409. func (s *scope) nearestFunction() *scope {
  410. for sc := s; sc != nil; sc = sc.outer {
  411. if sc.function {
  412. return sc
  413. }
  414. }
  415. return nil
  416. }
  417. func (s *scope) finaliseVarAlloc(stackOffset int) (stashSize, stackSize int) {
  418. argsInStash := false
  419. if f := s.nearestFunction(); f != nil {
  420. argsInStash = f.argsInStash
  421. }
  422. stackIdx, stashIdx := 0, 0
  423. allInStash := s.isDynamic()
  424. for i, b := range s.bindings {
  425. if allInStash || b.inStash {
  426. for scope, aps := range b.accessPoints {
  427. var level uint32
  428. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  429. if sc.needStash || sc.isDynamic() {
  430. level++
  431. }
  432. }
  433. if level > 255 {
  434. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  435. }
  436. idx := (level << 24) | uint32(stashIdx)
  437. base := scope.base
  438. code := scope.prg.code
  439. for _, pc := range *aps {
  440. ap := &code[base+pc]
  441. switch i := (*ap).(type) {
  442. case loadStash:
  443. *ap = loadStash(idx)
  444. case storeStash:
  445. *ap = storeStash(idx)
  446. case storeStashP:
  447. *ap = storeStashP(idx)
  448. case loadStashLex:
  449. *ap = loadStashLex(idx)
  450. case storeStashLex:
  451. *ap = storeStashLex(idx)
  452. case storeStashLexP:
  453. *ap = storeStashLexP(idx)
  454. case initStash:
  455. *ap = initStash(idx)
  456. case *loadMixed:
  457. i.idx = idx
  458. case *loadMixedLex:
  459. i.idx = idx
  460. case *resolveMixed:
  461. i.idx = idx
  462. }
  463. }
  464. }
  465. stashIdx++
  466. } else {
  467. var idx int
  468. if i < s.numArgs {
  469. idx = -(i + 1)
  470. } else {
  471. stackIdx++
  472. idx = stackIdx + stackOffset
  473. }
  474. for scope, aps := range b.accessPoints {
  475. var level int
  476. for sc := scope; sc != nil && sc != s; sc = sc.outer {
  477. if sc.needStash || sc.isDynamic() {
  478. level++
  479. }
  480. }
  481. if level > 255 {
  482. s.c.throwSyntaxError(0, "Maximum nesting level (256) exceeded")
  483. }
  484. code := scope.prg.code
  485. base := scope.base
  486. if argsInStash {
  487. for _, pc := range *aps {
  488. ap := &code[base+pc]
  489. switch i := (*ap).(type) {
  490. case loadStash:
  491. *ap = loadStack1(idx)
  492. case storeStash:
  493. *ap = storeStack1(idx)
  494. case storeStashP:
  495. *ap = storeStack1P(idx)
  496. case loadStashLex:
  497. *ap = loadStack1Lex(idx)
  498. case storeStashLex:
  499. *ap = storeStack1Lex(idx)
  500. case storeStashLexP:
  501. *ap = storeStack1LexP(idx)
  502. case initStash:
  503. *ap = initStack1(idx)
  504. case *loadMixed:
  505. *ap = &loadMixedStack1{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  506. case *loadMixedLex:
  507. *ap = &loadMixedStack1Lex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  508. case *resolveMixed:
  509. *ap = &resolveMixedStack1{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  510. }
  511. }
  512. } else {
  513. for _, pc := range *aps {
  514. ap := &code[base+pc]
  515. switch i := (*ap).(type) {
  516. case loadStash:
  517. *ap = loadStack(idx)
  518. case storeStash:
  519. *ap = storeStack(idx)
  520. case storeStashP:
  521. *ap = storeStackP(idx)
  522. case loadStashLex:
  523. *ap = loadStackLex(idx)
  524. case storeStashLex:
  525. *ap = storeStackLex(idx)
  526. case storeStashLexP:
  527. *ap = storeStackLexP(idx)
  528. case initStash:
  529. *ap = initStack(idx)
  530. case *loadMixed:
  531. *ap = &loadMixedStack{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  532. case *loadMixedLex:
  533. *ap = &loadMixedStackLex{name: i.name, idx: idx, level: uint8(level), callee: i.callee}
  534. case *resolveMixed:
  535. *ap = &resolveMixedStack{typ: i.typ, name: i.name, idx: idx, level: uint8(level), strict: i.strict}
  536. }
  537. }
  538. }
  539. }
  540. }
  541. }
  542. for _, nested := range s.nested {
  543. nested.finaliseVarAlloc(stackIdx + stackOffset)
  544. }
  545. return stashIdx, stackIdx
  546. }
  547. func (s *scope) moveArgsToStash() {
  548. for _, b := range s.bindings {
  549. if !b.isArg {
  550. break
  551. }
  552. b.inStash = true
  553. }
  554. s.argsInStash = true
  555. s.needStash = true
  556. }
  557. func (s *scope) adjustBase(delta int) {
  558. s.base += delta
  559. for _, nested := range s.nested {
  560. nested.adjustBase(delta)
  561. }
  562. }
  563. func (s *scope) makeNamesMap() map[unistring.String]uint32 {
  564. l := len(s.bindings)
  565. if l == 0 {
  566. return nil
  567. }
  568. names := make(map[unistring.String]uint32, l)
  569. for i, b := range s.bindings {
  570. idx := uint32(i)
  571. if b.isConst {
  572. idx |= maskConst
  573. if b.isStrict {
  574. idx |= maskStrict
  575. }
  576. }
  577. if b.isVar {
  578. idx |= maskVar
  579. }
  580. names[b.name] = idx
  581. }
  582. return names
  583. }
  584. func (s *scope) isDynamic() bool {
  585. return s.dynLookup || s.dynamic
  586. }
  587. func (s *scope) deleteBinding(b *binding) {
  588. idx := 0
  589. for i, bb := range s.bindings {
  590. if bb == b {
  591. idx = i
  592. goto found
  593. }
  594. }
  595. return
  596. found:
  597. delete(s.boundNames, b.name)
  598. copy(s.bindings[idx:], s.bindings[idx+1:])
  599. l := len(s.bindings) - 1
  600. s.bindings[l] = nil
  601. s.bindings = s.bindings[:l]
  602. }
  603. func (c *compiler) compile(in *ast.Program, strict, eval, inGlobal bool) {
  604. c.p.src = in.File
  605. c.newScope()
  606. scope := c.scope
  607. scope.dynamic = true
  608. scope.eval = eval
  609. if !strict && len(in.Body) > 0 {
  610. strict = c.isStrict(in.Body) != nil
  611. }
  612. scope.strict = strict
  613. ownVarScope := eval && strict
  614. ownLexScope := !inGlobal || eval
  615. if ownVarScope {
  616. c.newBlockScope()
  617. scope = c.scope
  618. scope.function = true
  619. }
  620. funcs := c.extractFunctions(in.Body)
  621. c.createFunctionBindings(funcs)
  622. numFuncs := len(scope.bindings)
  623. if inGlobal && !ownVarScope {
  624. if numFuncs == len(funcs) {
  625. c.compileFunctionsGlobalAllUnique(funcs)
  626. } else {
  627. c.compileFunctionsGlobal(funcs)
  628. }
  629. }
  630. c.compileDeclList(in.DeclarationList, false)
  631. numVars := len(scope.bindings) - numFuncs
  632. vars := make([]unistring.String, len(scope.bindings))
  633. for i, b := range scope.bindings {
  634. vars[i] = b.name
  635. }
  636. if len(vars) > 0 && !ownVarScope && ownLexScope {
  637. if inGlobal {
  638. c.emit(&bindGlobal{
  639. vars: vars[numFuncs:],
  640. funcs: vars[:numFuncs],
  641. deletable: eval,
  642. })
  643. } else {
  644. c.emit(&bindVars{names: vars, deletable: eval})
  645. }
  646. }
  647. var enter *enterBlock
  648. if c.compileLexicalDeclarations(in.Body, ownVarScope || !ownLexScope) {
  649. if ownLexScope {
  650. c.block = &block{
  651. outer: c.block,
  652. typ: blockScope,
  653. needResult: true,
  654. }
  655. enter = &enterBlock{}
  656. c.emit(enter)
  657. }
  658. }
  659. if len(scope.bindings) > 0 && !ownLexScope {
  660. var lets, consts []unistring.String
  661. for _, b := range c.scope.bindings[numFuncs+numVars:] {
  662. if b.isConst {
  663. consts = append(consts, b.name)
  664. } else {
  665. lets = append(lets, b.name)
  666. }
  667. }
  668. c.emit(&bindGlobal{
  669. vars: vars[numFuncs:],
  670. funcs: vars[:numFuncs],
  671. lets: lets,
  672. consts: consts,
  673. })
  674. }
  675. if !inGlobal || ownVarScope {
  676. c.compileFunctions(funcs)
  677. }
  678. c.compileStatements(in.Body, true)
  679. if enter != nil {
  680. c.leaveScopeBlock(enter)
  681. c.popScope()
  682. }
  683. c.p.code = append(c.p.code, halt)
  684. scope.finaliseVarAlloc(0)
  685. }
  686. func (c *compiler) compileDeclList(v []*ast.VariableDeclaration, inFunc bool) {
  687. for _, value := range v {
  688. c.createVarBindings(value, inFunc)
  689. }
  690. }
  691. func (c *compiler) extractLabelled(st ast.Statement) ast.Statement {
  692. if st, ok := st.(*ast.LabelledStatement); ok {
  693. return c.extractLabelled(st.Statement)
  694. }
  695. return st
  696. }
  697. func (c *compiler) extractFunctions(list []ast.Statement) (funcs []*ast.FunctionDeclaration) {
  698. for _, st := range list {
  699. var decl *ast.FunctionDeclaration
  700. switch st := c.extractLabelled(st).(type) {
  701. case *ast.FunctionDeclaration:
  702. decl = st
  703. case *ast.LabelledStatement:
  704. if st1, ok := st.Statement.(*ast.FunctionDeclaration); ok {
  705. decl = st1
  706. } else {
  707. continue
  708. }
  709. default:
  710. continue
  711. }
  712. funcs = append(funcs, decl)
  713. }
  714. return
  715. }
  716. func (c *compiler) createFunctionBindings(funcs []*ast.FunctionDeclaration) {
  717. s := c.scope
  718. if s.outer != nil {
  719. unique := !s.function && !s.variable && s.strict
  720. for _, decl := range funcs {
  721. s.bindNameLexical(decl.Function.Name.Name, unique, int(decl.Function.Name.Idx1())-1)
  722. }
  723. } else {
  724. for _, decl := range funcs {
  725. s.bindName(decl.Function.Name.Name)
  726. }
  727. }
  728. }
  729. func (c *compiler) compileFunctions(list []*ast.FunctionDeclaration) {
  730. for _, decl := range list {
  731. c.compileFunction(decl)
  732. }
  733. }
  734. func (c *compiler) compileFunctionsGlobalAllUnique(list []*ast.FunctionDeclaration) {
  735. for _, decl := range list {
  736. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  737. }
  738. }
  739. func (c *compiler) compileFunctionsGlobal(list []*ast.FunctionDeclaration) {
  740. m := make(map[unistring.String]int, len(list))
  741. for i := len(list) - 1; i >= 0; i-- {
  742. name := list[i].Function.Name.Name
  743. if _, exists := m[name]; !exists {
  744. m[name] = i
  745. }
  746. }
  747. for i, decl := range list {
  748. if m[decl.Function.Name.Name] == i {
  749. c.compileFunctionLiteral(decl.Function, false).emitGetter(true)
  750. } else {
  751. leave := c.enterDummyMode()
  752. c.compileFunctionLiteral(decl.Function, false).emitGetter(false)
  753. leave()
  754. }
  755. }
  756. }
  757. func (c *compiler) createVarIdBinding(name unistring.String, offset int, inFunc bool) {
  758. if c.scope.strict {
  759. c.checkIdentifierLName(name, offset)
  760. c.checkIdentifierName(name, offset)
  761. }
  762. if !inFunc || name != "arguments" {
  763. c.scope.bindName(name)
  764. }
  765. }
  766. func (c *compiler) createBindings(target ast.Expression, createIdBinding func(name unistring.String, offset int)) {
  767. switch target := target.(type) {
  768. case *ast.Identifier:
  769. createIdBinding(target.Name, int(target.Idx)-1)
  770. case *ast.ObjectPattern:
  771. for _, prop := range target.Properties {
  772. switch prop := prop.(type) {
  773. case *ast.PropertyShort:
  774. createIdBinding(prop.Name.Name, int(prop.Name.Idx)-1)
  775. case *ast.PropertyKeyed:
  776. c.createBindings(prop.Value, createIdBinding)
  777. default:
  778. c.throwSyntaxError(int(target.Idx0()-1), "unsupported property type in ObjectPattern: %T", prop)
  779. }
  780. }
  781. if target.Rest != nil {
  782. c.createBindings(target.Rest, createIdBinding)
  783. }
  784. case *ast.ArrayPattern:
  785. for _, elt := range target.Elements {
  786. if elt != nil {
  787. c.createBindings(elt, createIdBinding)
  788. }
  789. }
  790. if target.Rest != nil {
  791. c.createBindings(target.Rest, createIdBinding)
  792. }
  793. case *ast.AssignExpression:
  794. c.createBindings(target.Left, createIdBinding)
  795. default:
  796. c.throwSyntaxError(int(target.Idx0()-1), "unsupported binding target: %T", target)
  797. }
  798. }
  799. func (c *compiler) createVarBinding(target ast.Expression, inFunc bool) {
  800. c.createBindings(target, func(name unistring.String, offset int) {
  801. c.createVarIdBinding(name, offset, inFunc)
  802. })
  803. }
  804. func (c *compiler) createVarBindings(v *ast.VariableDeclaration, inFunc bool) {
  805. for _, item := range v.List {
  806. c.createVarBinding(item.Target, inFunc)
  807. }
  808. }
  809. func (c *compiler) createLexicalIdBinding(name unistring.String, isConst bool, offset int) *binding {
  810. if name == "let" {
  811. c.throwSyntaxError(offset, "let is disallowed as a lexically bound name")
  812. }
  813. if c.scope.strict {
  814. c.checkIdentifierLName(name, offset)
  815. c.checkIdentifierName(name, offset)
  816. }
  817. b, _ := c.scope.bindNameLexical(name, true, offset)
  818. if isConst {
  819. b.isConst, b.isStrict = true, true
  820. }
  821. return b
  822. }
  823. func (c *compiler) createLexicalIdBindingFuncBody(name unistring.String, isConst bool, offset int, calleeBinding *binding) *binding {
  824. if name == "let" {
  825. c.throwSyntaxError(offset, "let is disallowed as a lexically bound name")
  826. }
  827. if c.scope.strict {
  828. c.checkIdentifierLName(name, offset)
  829. c.checkIdentifierName(name, offset)
  830. }
  831. paramScope := c.scope.outer
  832. parentBinding := paramScope.boundNames[name]
  833. if parentBinding != nil {
  834. if parentBinding != calleeBinding && (name != "arguments" || !paramScope.argsNeeded) {
  835. c.throwSyntaxError(offset, "Identifier '%s' has already been declared", name)
  836. }
  837. }
  838. b, _ := c.scope.bindNameLexical(name, true, offset)
  839. if isConst {
  840. b.isConst, b.isStrict = true, true
  841. }
  842. return b
  843. }
  844. func (c *compiler) createLexicalBinding(target ast.Expression, isConst bool) {
  845. c.createBindings(target, func(name unistring.String, offset int) {
  846. c.createLexicalIdBinding(name, isConst, offset)
  847. })
  848. }
  849. func (c *compiler) createLexicalBindings(lex *ast.LexicalDeclaration) {
  850. for _, d := range lex.List {
  851. c.createLexicalBinding(d.Target, lex.Token == token.CONST)
  852. }
  853. }
  854. func (c *compiler) compileLexicalDeclarations(list []ast.Statement, scopeDeclared bool) bool {
  855. for _, st := range list {
  856. if lex, ok := st.(*ast.LexicalDeclaration); ok {
  857. if !scopeDeclared {
  858. c.newBlockScope()
  859. scopeDeclared = true
  860. }
  861. c.createLexicalBindings(lex)
  862. }
  863. }
  864. return scopeDeclared
  865. }
  866. func (c *compiler) compileLexicalDeclarationsFuncBody(list []ast.Statement, calleeBinding *binding) {
  867. for _, st := range list {
  868. if lex, ok := st.(*ast.LexicalDeclaration); ok {
  869. isConst := lex.Token == token.CONST
  870. for _, d := range lex.List {
  871. c.createBindings(d.Target, func(name unistring.String, offset int) {
  872. c.createLexicalIdBindingFuncBody(name, isConst, offset, calleeBinding)
  873. })
  874. }
  875. }
  876. }
  877. }
  878. func (c *compiler) compileFunction(v *ast.FunctionDeclaration) {
  879. name := v.Function.Name.Name
  880. b := c.scope.boundNames[name]
  881. if b == nil || b.isVar {
  882. e := &compiledIdentifierExpr{
  883. name: v.Function.Name.Name,
  884. }
  885. e.init(c, v.Function.Idx0())
  886. e.emitSetter(c.compileFunctionLiteral(v.Function, false), false)
  887. } else {
  888. c.compileFunctionLiteral(v.Function, false).emitGetter(true)
  889. b.emitInit()
  890. }
  891. }
  892. func (c *compiler) compileStandaloneFunctionDecl(v *ast.FunctionDeclaration) {
  893. if c.scope.strict {
  894. c.throwSyntaxError(int(v.Idx0())-1, "In strict mode code, functions can only be declared at top level or inside a block.")
  895. }
  896. 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.")
  897. }
  898. func (c *compiler) emit(instructions ...instruction) {
  899. c.p.code = append(c.p.code, instructions...)
  900. }
  901. func (c *compiler) throwSyntaxError(offset int, format string, args ...interface{}) {
  902. panic(&CompilerSyntaxError{
  903. CompilerError: CompilerError{
  904. File: c.p.src,
  905. Offset: offset,
  906. Message: fmt.Sprintf(format, args...),
  907. },
  908. })
  909. }
  910. func (c *compiler) isStrict(list []ast.Statement) *ast.StringLiteral {
  911. for _, st := range list {
  912. if st, ok := st.(*ast.ExpressionStatement); ok {
  913. if e, ok := st.Expression.(*ast.StringLiteral); ok {
  914. if e.Literal == `"use strict"` || e.Literal == `'use strict'` {
  915. return e
  916. }
  917. } else {
  918. break
  919. }
  920. } else {
  921. break
  922. }
  923. }
  924. return nil
  925. }
  926. func (c *compiler) isStrictStatement(s ast.Statement) *ast.StringLiteral {
  927. if s, ok := s.(*ast.BlockStatement); ok {
  928. return c.isStrict(s.List)
  929. }
  930. return nil
  931. }
  932. func (c *compiler) checkIdentifierName(name unistring.String, offset int) {
  933. switch name {
  934. case "implements", "interface", "let", "package", "private", "protected", "public", "static", "yield":
  935. c.throwSyntaxError(offset, "Unexpected strict mode reserved word")
  936. }
  937. }
  938. func (c *compiler) checkIdentifierLName(name unistring.String, offset int) {
  939. switch name {
  940. case "eval", "arguments":
  941. c.throwSyntaxError(offset, "Assignment to eval or arguments is not allowed in strict mode")
  942. }
  943. }
  944. // Enter a 'dummy' compilation mode. Any code produced after this method is called will be discarded after
  945. // leaveFunc is called with no additional side effects. This is useful for compiling code inside a
  946. // constant falsy condition 'if' branch or a loop (i.e 'if (false) { ... } or while (false) { ... }).
  947. // Such code should not be included in the final compilation result as it's never called, but it must
  948. // still produce compilation errors if there are any.
  949. // TODO: make sure variable lookups do not de-optimise parent scopes
  950. func (c *compiler) enterDummyMode() (leaveFunc func()) {
  951. savedBlock, savedProgram := c.block, c.p
  952. if savedBlock != nil {
  953. c.block = &block{
  954. typ: savedBlock.typ,
  955. label: savedBlock.label,
  956. outer: savedBlock.outer,
  957. breaking: savedBlock.breaking,
  958. }
  959. }
  960. c.p = &Program{}
  961. c.newScope()
  962. return func() {
  963. c.block, c.p = savedBlock, savedProgram
  964. c.popScope()
  965. }
  966. }
  967. func (c *compiler) compileStatementDummy(statement ast.Statement) {
  968. leave := c.enterDummyMode()
  969. c.compileStatement(statement, false)
  970. leave()
  971. }