compiler.go 25 KB

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