compiler.go 25 KB

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