compiler.go 25 KB

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