compiler.go 20 KB

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